stackone-ai 2.7.0__tar.gz → 2.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- stackone_ai-2.8.0/.env.example +6 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.gitignore +1 -0
- stackone_ai-2.8.0/.release-please-manifest.json +3 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/CHANGELOG.md +7 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/PKG-INFO +57 -32
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/README.md +52 -28
- stackone_ai-2.8.0/examples/auth_management.py +103 -0
- stackone_ai-2.8.0/examples/crewai_integration.py +69 -0
- stackone_ai-2.8.0/examples/langchain_integration.py +69 -0
- stackone_ai-2.8.0/examples/langgraph_integration.py +62 -0
- stackone_ai-2.8.0/examples/openai_integration.py +113 -0
- stackone_ai-2.8.0/examples/pydantic_ai_integration.py +65 -0
- stackone_ai-2.8.0/examples/search_tools.py +171 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/examples/test_examples.py +4 -8
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/justfile +4 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/pyproject.toml +5 -4
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/__init__.py +1 -1
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/uv.lock +1383 -472
- stackone_ai-2.7.0/.release-please-manifest.json +0 -3
- stackone_ai-2.7.0/examples/agent_tool_search.py +0 -202
- stackone_ai-2.7.0/examples/crewai_integration.py +0 -55
- stackone_ai-2.7.0/examples/file_uploads.py +0 -83
- stackone_ai-2.7.0/examples/index.py +0 -105
- stackone_ai-2.7.0/examples/langchain_integration.py +0 -51
- stackone_ai-2.7.0/examples/openai_integration.py +0 -93
- stackone_ai-2.7.0/examples/search_tool_example.py +0 -66
- stackone_ai-2.7.0/examples/semantic_search_example.py +0 -423
- stackone_ai-2.7.0/examples/stackone_account_ids.py +0 -40
- stackone_ai-2.7.0/examples/workday_integration.py +0 -91
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.claude/rules/development-workflow.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.claude/rules/examples-standards.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.claude/rules/git-workflow.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.claude/rules/nix-workflow.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.claude/rules/no-relative-imports.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.claude/rules/package-installation.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.claude/rules/release-please-standards.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.claude/rules/uv-scripts.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.cursor/rules/development-workflow.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.cursor/rules/examples-standards.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.cursor/rules/git-workflow.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.cursor/rules/no-relative-imports.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.cursor/rules/package-installation.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.cursor/rules/release-please-standards.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.cursor/rules/uv-scripts.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.envrc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.github/actions/setup-nix/action.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.github/dependabot.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.github/workflows/ci.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.github/workflows/nix-flake-update.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.github/workflows/nix-flake.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.github/workflows/release.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.gitleaks.toml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.gitmodules +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.mcp.json +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/.release-please-config.json +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/CLAUDE.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/LICENSE +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/flake.lock +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/flake.nix +0 -0
- {stackone_ai-2.7.0/examples → stackone_ai-2.8.0/scripts}/benchmark_search.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/constants.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/feedback/__init__.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/feedback/tool.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/integrations/__init__.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/integrations/langgraph.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/local_search.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/models.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/py.typed +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/semantic_search.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/toolset.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/utils/__init__.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/utils/normalize.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/stackone_ai/utils/tfidf_index.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/tests/conftest.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/tests/mocks/serve.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/tests/test_agent_tools.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/tests/test_feedback.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/tests/test_fetch_tools.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/tests/test_integrations_langgraph.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/tests/test_local_search.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/tests/test_models.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/tests/test_semantic_search.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/tests/test_tfidf_index.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/tests/test_tool_calling.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/tests/test_toolset.py +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/rules/development-workflow.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/rules/file-operations.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/rules/git-workflow.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/rules/pnpm-usage.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/rules/typescript-patterns.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/rules/typescript-testing.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/skills/orama-integration/SKILL.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/development-workflow.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/file-operations.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/git-workflow.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/orama-integration.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/pnpm-usage.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/typescript-patterns.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/typescript-testing.mdc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.envrc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.git +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/CODEOWNERS +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/actions/setup-nix/action.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/workflows/check-title.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/workflows/ci.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/workflows/claude.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/workflows/dry-publish.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/workflows/nix-flake.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/workflows/release.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.gitignore +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.gitleaks.toml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.mcp.json +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.oxfmtrc.jsonc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.oxlintrc.jsonc +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/AGENTS.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/CHANGELOG.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/CLAUDE.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/LICENSE +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/README.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/README.md +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/ai-sdk-integration.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/ai-sdk-integration.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/anthropic-integration.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/claude-agent-sdk-integration.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/claude-agent-sdk-integration.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/fetch-tools-debug.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/fetch-tools.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/fetch-tools.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/meta-tools.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/openai-integration.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/openai-integration.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/openai-responses-integration.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/openai-responses-integration.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/package.json +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/tanstack-ai-integration.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/tanstack-ai-integration.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/tsconfig.json +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/flake.lock +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/flake.nix +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/knip.config.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/lefthook.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.example-api.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.mcp.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.openai.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.stackone-ai.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.stackone-rpc.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.utils.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/mcp-server.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/node.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/package.json +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/pnpm-lock.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/pnpm-workspace.yaml +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/consts.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/feedback.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/feedback.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/headers.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/headers.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/index.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/mcp-client.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/mcp-client.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/requestBuilder.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/requestBuilder.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/rpc-client.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/rpc-client.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/schema.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/tool.test-d.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/tool.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/tool.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/toolsets.test-d.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/toolsets.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/toolsets.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/types.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/array.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/array.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/error-stackone-api.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/error-stackone-api.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/error-stackone.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/error-stackone.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/tfidf-index.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/tfidf-index.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/try-import.test.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/try-import.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/type.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/tsconfig.json +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/tsdown.config.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/vitest.config.ts +0 -0
- {stackone_ai-2.7.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/vitest.setup.ts +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.8.0](https://github.com/StackOneHQ/stackone-ai-python/compare/stackone-ai-v2.7.0...stackone-ai-v2.8.0) (2026-04-20)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **examples:** streamline examples, standardize auth patterns and migrate examples to Workday ([#179](https://github.com/StackOneHQ/stackone-ai-python/issues/179)) ([0bdc939](https://github.com/StackOneHQ/stackone-ai-python/commit/0bdc939e2844a0dae6bf527c8c8209df0a90d1f7))
|
|
9
|
+
|
|
3
10
|
## [2.7.0](https://github.com/StackOneHQ/stackone-ai-python/compare/stackone-ai-v2.6.0...stackone-ai-v2.7.0) (2026-04-14)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stackone-ai
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.0
|
|
4
4
|
Summary: agents performing actions on your SaaS
|
|
5
5
|
Author-email: StackOne <support@stackone.com>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -22,9 +22,10 @@ Requires-Dist: pydantic>=2.10.6
|
|
|
22
22
|
Requires-Dist: typing-extensions>=4.0.0
|
|
23
23
|
Provides-Extra: examples
|
|
24
24
|
Requires-Dist: crewai>=0.102.0; extra == 'examples'
|
|
25
|
-
Requires-Dist: langchain-openai>=
|
|
26
|
-
Requires-Dist: langgraph>=
|
|
27
|
-
Requires-Dist: openai>=
|
|
25
|
+
Requires-Dist: langchain-openai>=1.1.14; extra == 'examples'
|
|
26
|
+
Requires-Dist: langgraph>=1.1.6; extra == 'examples'
|
|
27
|
+
Requires-Dist: openai>=2.32.0; extra == 'examples'
|
|
28
|
+
Requires-Dist: pydantic-ai>=1.83.0; extra == 'examples'
|
|
28
29
|
Requires-Dist: python-dotenv>=1.0.1; extra == 'examples'
|
|
29
30
|
Provides-Extra: mcp
|
|
30
31
|
Requires-Dist: mcp>=1.3.0; extra == 'mcp'
|
|
@@ -84,17 +85,18 @@ uv add 'stackone-ai[mcp,examples]'
|
|
|
84
85
|
## Quick Start
|
|
85
86
|
|
|
86
87
|
```python
|
|
88
|
+
import os
|
|
87
89
|
from stackone_ai import StackOneToolSet
|
|
88
90
|
|
|
89
|
-
# Initialize
|
|
90
|
-
toolset = StackOneToolSet()
|
|
91
|
-
# Or explicitly: toolset = StackOneToolSet(api_key="your-api-key")
|
|
91
|
+
# Initialize — reads STACKONE_API_KEY from environment
|
|
92
|
+
toolset = StackOneToolSet()
|
|
92
93
|
|
|
93
|
-
#
|
|
94
|
-
|
|
94
|
+
# Fetch tools — pass account ID from STACKONE_ACCOUNT_ID env var
|
|
95
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
96
|
+
tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id])
|
|
95
97
|
|
|
96
98
|
# Use a specific tool with the call method
|
|
97
|
-
employee_tool = tools.get_tool("
|
|
99
|
+
employee_tool = tools.get_tool("workday_get_worker")
|
|
98
100
|
# Call with keyword arguments
|
|
99
101
|
employee = employee_tool.call(id="employee-id")
|
|
100
102
|
# Or with traditional execute method
|
|
@@ -118,7 +120,7 @@ toolset = StackOneToolSet()
|
|
|
118
120
|
tools = toolset.fetch_tools(account_ids=["acc-123", "acc-456"])
|
|
119
121
|
|
|
120
122
|
# Filter by providers (case-insensitive)
|
|
121
|
-
tools = toolset.fetch_tools(providers=["hibob", "
|
|
123
|
+
tools = toolset.fetch_tools(providers=["hibob", "workday"])
|
|
122
124
|
|
|
123
125
|
# Filter by action patterns with glob support
|
|
124
126
|
tools = toolset.fetch_tools(actions=["*_list_employees"])
|
|
@@ -138,11 +140,11 @@ tools = toolset.fetch_tools(providers=["hibob"])
|
|
|
138
140
|
**Filtering Options:**
|
|
139
141
|
|
|
140
142
|
- **`account_ids`**: Filter tools by account IDs. Tools will be loaded for each specified account.
|
|
141
|
-
- **`providers`**: Filter by provider names (e.g., `["hibob", "
|
|
143
|
+
- **`providers`**: Filter by provider names (e.g., `["hibob", "workday"]`). Case-insensitive matching.
|
|
142
144
|
- **`actions`**: Filter by action patterns with glob support:
|
|
143
|
-
- Exact match: `["
|
|
145
|
+
- Exact match: `["workday_list_workers"]`
|
|
144
146
|
- Glob pattern: `["*_list_employees"]` matches all tools ending with `_list_employees`
|
|
145
|
-
- Provider prefix: `["
|
|
147
|
+
- Provider prefix: `["workday_*"]` matches all Workday tools
|
|
146
148
|
|
|
147
149
|
## Implicit Feedback (Beta)
|
|
148
150
|
|
|
@@ -197,18 +199,20 @@ When two calls for the same session happen within a few seconds, the SDK emits a
|
|
|
197
199
|
StackOne tools work seamlessly with LangChain, enabling powerful AI agent workflows:
|
|
198
200
|
|
|
199
201
|
```python
|
|
202
|
+
import os
|
|
200
203
|
from langchain_openai import ChatOpenAI
|
|
201
204
|
from stackone_ai import StackOneToolSet
|
|
202
205
|
|
|
203
206
|
# Initialize StackOne tools
|
|
204
207
|
toolset = StackOneToolSet()
|
|
205
|
-
|
|
208
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
209
|
+
tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id])
|
|
206
210
|
|
|
207
211
|
# Convert to LangChain format
|
|
208
212
|
langchain_tools = tools.to_langchain()
|
|
209
213
|
|
|
210
214
|
# Use with LangChain models
|
|
211
|
-
model = ChatOpenAI(model="gpt-
|
|
215
|
+
model = ChatOpenAI(model="gpt-5.4")
|
|
212
216
|
model_with_tools = model.bind_tools(langchain_tools)
|
|
213
217
|
|
|
214
218
|
# Execute AI-driven tool calls
|
|
@@ -236,6 +240,7 @@ pip install langgraph langchain-openai
|
|
|
236
240
|
```
|
|
237
241
|
|
|
238
242
|
```python
|
|
243
|
+
import os
|
|
239
244
|
from langchain_openai import ChatOpenAI
|
|
240
245
|
from typing import Annotated
|
|
241
246
|
from typing_extensions import TypedDict
|
|
@@ -249,7 +254,8 @@ from stackone_ai.integrations.langgraph import to_tool_node, bind_model_with_too
|
|
|
249
254
|
|
|
250
255
|
# Prepare tools
|
|
251
256
|
toolset = StackOneToolSet()
|
|
252
|
-
|
|
257
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
258
|
+
tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id])
|
|
253
259
|
langchain_tools = tools.to_langchain()
|
|
254
260
|
|
|
255
261
|
class State(TypedDict):
|
|
@@ -260,7 +266,7 @@ graph = StateGraph(State)
|
|
|
260
266
|
graph.add_node("tools", to_tool_node(langchain_tools))
|
|
261
267
|
|
|
262
268
|
def call_llm(state: dict):
|
|
263
|
-
llm = ChatOpenAI(model="gpt-
|
|
269
|
+
llm = ChatOpenAI(model="gpt-5.4")
|
|
264
270
|
llm = bind_model_with_tools(llm, langchain_tools)
|
|
265
271
|
resp = llm.invoke(state["messages"]) # returns AIMessage with optional tool_calls
|
|
266
272
|
return {"messages": state["messages"] + [resp]}
|
|
@@ -282,12 +288,14 @@ _ = app.invoke({"messages": [("user", "Get employee with id emp123") ]})
|
|
|
282
288
|
CrewAI uses LangChain tools natively, making integration seamless:
|
|
283
289
|
|
|
284
290
|
```python
|
|
291
|
+
import os
|
|
285
292
|
from crewai import Agent, Crew, Task
|
|
286
293
|
from stackone_ai import StackOneToolSet
|
|
287
294
|
|
|
288
295
|
# Get tools and convert to LangChain format
|
|
289
296
|
toolset = StackOneToolSet()
|
|
290
|
-
|
|
297
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
298
|
+
tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id])
|
|
291
299
|
langchain_tools = tools.to_langchain()
|
|
292
300
|
|
|
293
301
|
# Create CrewAI agent with StackOne tools
|
|
@@ -296,7 +304,7 @@ agent = Agent(
|
|
|
296
304
|
goal="Analyze employee data and generate insights",
|
|
297
305
|
backstory="Expert in HR analytics and employee management",
|
|
298
306
|
tools=langchain_tools,
|
|
299
|
-
llm="gpt-
|
|
307
|
+
llm="gpt-5.4"
|
|
300
308
|
)
|
|
301
309
|
|
|
302
310
|
# Define task and execute
|
|
@@ -329,7 +337,7 @@ feedback_tool = tools.get_tool("tool_feedback")
|
|
|
329
337
|
result = feedback_tool.call(
|
|
330
338
|
feedback="The HRIS tools are working great! Very fast response times.",
|
|
331
339
|
account_id="acc_123456",
|
|
332
|
-
tool_names=["
|
|
340
|
+
tool_names=["workday_list_workers", "workday_get_worker"]
|
|
333
341
|
)
|
|
334
342
|
```
|
|
335
343
|
|
|
@@ -345,9 +353,12 @@ Search for tools using natural language queries. Works with both semantic (cloud
|
|
|
345
353
|
### Basic Usage
|
|
346
354
|
|
|
347
355
|
```python
|
|
356
|
+
import os
|
|
357
|
+
|
|
348
358
|
# Get a callable search tool
|
|
349
359
|
toolset = StackOneToolSet()
|
|
350
|
-
|
|
360
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
361
|
+
all_tools = toolset.fetch_tools(account_ids=[account_id])
|
|
351
362
|
search_tool = toolset.get_search_tool()
|
|
352
363
|
|
|
353
364
|
# Search for relevant tools — returns a Tools collection
|
|
@@ -359,15 +370,17 @@ tools[0](limit=10)
|
|
|
359
370
|
|
|
360
371
|
## Semantic Search
|
|
361
372
|
|
|
362
|
-
Discover tools using natural language instead of exact names. Queries like "onboard new hire" resolve to the right actions even when the tool is called `
|
|
373
|
+
Discover tools using natural language instead of exact names. Queries like "onboard new hire" resolve to the right actions even when the tool is called `workday_create_employee`.
|
|
363
374
|
|
|
364
375
|
```python
|
|
376
|
+
import os
|
|
365
377
|
from stackone_ai import StackOneToolSet
|
|
366
378
|
|
|
367
379
|
toolset = StackOneToolSet()
|
|
368
380
|
|
|
369
381
|
# Search by intent — returns Tools collection ready for any framework
|
|
370
|
-
|
|
382
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
383
|
+
tools = toolset.search_tools("manage employee records", account_ids=[account_id], top_k=5)
|
|
371
384
|
openai_tools = tools.to_openai()
|
|
372
385
|
|
|
373
386
|
# Lightweight: inspect results without fetching full tool definitions
|
|
@@ -389,19 +402,31 @@ tools = toolset.search_tools("manage employees", search="semantic")
|
|
|
389
402
|
tools = toolset.search_tools("manage employees", search="local")
|
|
390
403
|
```
|
|
391
404
|
|
|
392
|
-
Results are automatically scoped to connectors in your linked accounts. See [
|
|
405
|
+
Results are automatically scoped to connectors in your linked accounts. See [Search Tools Example](examples/search_tools.py) for `SearchTool` (`get_search_tool`) integration, OpenAI, and LangChain patterns.
|
|
393
406
|
|
|
394
407
|
## Examples
|
|
395
408
|
|
|
396
409
|
For more examples, check out the [examples/](examples/) directory:
|
|
397
410
|
|
|
398
|
-
- [
|
|
399
|
-
- [
|
|
400
|
-
- [
|
|
401
|
-
- [
|
|
402
|
-
- [
|
|
403
|
-
|
|
404
|
-
|
|
411
|
+
- [OpenAI Integration](examples/openai_integration.py) — OpenAI function calling
|
|
412
|
+
- [LangChain Integration](examples/langchain_integration.py) — LangChain tools
|
|
413
|
+
- [CrewAI Integration](examples/crewai_integration.py) — CrewAI agent
|
|
414
|
+
- [Search Tools](examples/search_tools.py) — Tool discovery (semantic, local, auto search)
|
|
415
|
+
- [Auth Management](examples/auth_management.py) — API key and account ID patterns
|
|
416
|
+
|
|
417
|
+
### Running Examples
|
|
418
|
+
|
|
419
|
+
```bash
|
|
420
|
+
# 1. Set up credentials
|
|
421
|
+
cp .env.example .env
|
|
422
|
+
# Edit .env with your API keys
|
|
423
|
+
|
|
424
|
+
# 2. Install dependencies
|
|
425
|
+
uv sync --all-extras
|
|
426
|
+
|
|
427
|
+
# 3. Run any example
|
|
428
|
+
uv run examples/search_tools.py
|
|
429
|
+
```
|
|
405
430
|
|
|
406
431
|
## Development
|
|
407
432
|
|
|
@@ -52,17 +52,18 @@ uv add 'stackone-ai[mcp,examples]'
|
|
|
52
52
|
## Quick Start
|
|
53
53
|
|
|
54
54
|
```python
|
|
55
|
+
import os
|
|
55
56
|
from stackone_ai import StackOneToolSet
|
|
56
57
|
|
|
57
|
-
# Initialize
|
|
58
|
-
toolset = StackOneToolSet()
|
|
59
|
-
# Or explicitly: toolset = StackOneToolSet(api_key="your-api-key")
|
|
58
|
+
# Initialize — reads STACKONE_API_KEY from environment
|
|
59
|
+
toolset = StackOneToolSet()
|
|
60
60
|
|
|
61
|
-
#
|
|
62
|
-
|
|
61
|
+
# Fetch tools — pass account ID from STACKONE_ACCOUNT_ID env var
|
|
62
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
63
|
+
tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id])
|
|
63
64
|
|
|
64
65
|
# Use a specific tool with the call method
|
|
65
|
-
employee_tool = tools.get_tool("
|
|
66
|
+
employee_tool = tools.get_tool("workday_get_worker")
|
|
66
67
|
# Call with keyword arguments
|
|
67
68
|
employee = employee_tool.call(id="employee-id")
|
|
68
69
|
# Or with traditional execute method
|
|
@@ -86,7 +87,7 @@ toolset = StackOneToolSet()
|
|
|
86
87
|
tools = toolset.fetch_tools(account_ids=["acc-123", "acc-456"])
|
|
87
88
|
|
|
88
89
|
# Filter by providers (case-insensitive)
|
|
89
|
-
tools = toolset.fetch_tools(providers=["hibob", "
|
|
90
|
+
tools = toolset.fetch_tools(providers=["hibob", "workday"])
|
|
90
91
|
|
|
91
92
|
# Filter by action patterns with glob support
|
|
92
93
|
tools = toolset.fetch_tools(actions=["*_list_employees"])
|
|
@@ -106,11 +107,11 @@ tools = toolset.fetch_tools(providers=["hibob"])
|
|
|
106
107
|
**Filtering Options:**
|
|
107
108
|
|
|
108
109
|
- **`account_ids`**: Filter tools by account IDs. Tools will be loaded for each specified account.
|
|
109
|
-
- **`providers`**: Filter by provider names (e.g., `["hibob", "
|
|
110
|
+
- **`providers`**: Filter by provider names (e.g., `["hibob", "workday"]`). Case-insensitive matching.
|
|
110
111
|
- **`actions`**: Filter by action patterns with glob support:
|
|
111
|
-
- Exact match: `["
|
|
112
|
+
- Exact match: `["workday_list_workers"]`
|
|
112
113
|
- Glob pattern: `["*_list_employees"]` matches all tools ending with `_list_employees`
|
|
113
|
-
- Provider prefix: `["
|
|
114
|
+
- Provider prefix: `["workday_*"]` matches all Workday tools
|
|
114
115
|
|
|
115
116
|
## Implicit Feedback (Beta)
|
|
116
117
|
|
|
@@ -165,18 +166,20 @@ When two calls for the same session happen within a few seconds, the SDK emits a
|
|
|
165
166
|
StackOne tools work seamlessly with LangChain, enabling powerful AI agent workflows:
|
|
166
167
|
|
|
167
168
|
```python
|
|
169
|
+
import os
|
|
168
170
|
from langchain_openai import ChatOpenAI
|
|
169
171
|
from stackone_ai import StackOneToolSet
|
|
170
172
|
|
|
171
173
|
# Initialize StackOne tools
|
|
172
174
|
toolset = StackOneToolSet()
|
|
173
|
-
|
|
175
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
176
|
+
tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id])
|
|
174
177
|
|
|
175
178
|
# Convert to LangChain format
|
|
176
179
|
langchain_tools = tools.to_langchain()
|
|
177
180
|
|
|
178
181
|
# Use with LangChain models
|
|
179
|
-
model = ChatOpenAI(model="gpt-
|
|
182
|
+
model = ChatOpenAI(model="gpt-5.4")
|
|
180
183
|
model_with_tools = model.bind_tools(langchain_tools)
|
|
181
184
|
|
|
182
185
|
# Execute AI-driven tool calls
|
|
@@ -204,6 +207,7 @@ pip install langgraph langchain-openai
|
|
|
204
207
|
```
|
|
205
208
|
|
|
206
209
|
```python
|
|
210
|
+
import os
|
|
207
211
|
from langchain_openai import ChatOpenAI
|
|
208
212
|
from typing import Annotated
|
|
209
213
|
from typing_extensions import TypedDict
|
|
@@ -217,7 +221,8 @@ from stackone_ai.integrations.langgraph import to_tool_node, bind_model_with_too
|
|
|
217
221
|
|
|
218
222
|
# Prepare tools
|
|
219
223
|
toolset = StackOneToolSet()
|
|
220
|
-
|
|
224
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
225
|
+
tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id])
|
|
221
226
|
langchain_tools = tools.to_langchain()
|
|
222
227
|
|
|
223
228
|
class State(TypedDict):
|
|
@@ -228,7 +233,7 @@ graph = StateGraph(State)
|
|
|
228
233
|
graph.add_node("tools", to_tool_node(langchain_tools))
|
|
229
234
|
|
|
230
235
|
def call_llm(state: dict):
|
|
231
|
-
llm = ChatOpenAI(model="gpt-
|
|
236
|
+
llm = ChatOpenAI(model="gpt-5.4")
|
|
232
237
|
llm = bind_model_with_tools(llm, langchain_tools)
|
|
233
238
|
resp = llm.invoke(state["messages"]) # returns AIMessage with optional tool_calls
|
|
234
239
|
return {"messages": state["messages"] + [resp]}
|
|
@@ -250,12 +255,14 @@ _ = app.invoke({"messages": [("user", "Get employee with id emp123") ]})
|
|
|
250
255
|
CrewAI uses LangChain tools natively, making integration seamless:
|
|
251
256
|
|
|
252
257
|
```python
|
|
258
|
+
import os
|
|
253
259
|
from crewai import Agent, Crew, Task
|
|
254
260
|
from stackone_ai import StackOneToolSet
|
|
255
261
|
|
|
256
262
|
# Get tools and convert to LangChain format
|
|
257
263
|
toolset = StackOneToolSet()
|
|
258
|
-
|
|
264
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
265
|
+
tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id])
|
|
259
266
|
langchain_tools = tools.to_langchain()
|
|
260
267
|
|
|
261
268
|
# Create CrewAI agent with StackOne tools
|
|
@@ -264,7 +271,7 @@ agent = Agent(
|
|
|
264
271
|
goal="Analyze employee data and generate insights",
|
|
265
272
|
backstory="Expert in HR analytics and employee management",
|
|
266
273
|
tools=langchain_tools,
|
|
267
|
-
llm="gpt-
|
|
274
|
+
llm="gpt-5.4"
|
|
268
275
|
)
|
|
269
276
|
|
|
270
277
|
# Define task and execute
|
|
@@ -297,7 +304,7 @@ feedback_tool = tools.get_tool("tool_feedback")
|
|
|
297
304
|
result = feedback_tool.call(
|
|
298
305
|
feedback="The HRIS tools are working great! Very fast response times.",
|
|
299
306
|
account_id="acc_123456",
|
|
300
|
-
tool_names=["
|
|
307
|
+
tool_names=["workday_list_workers", "workday_get_worker"]
|
|
301
308
|
)
|
|
302
309
|
```
|
|
303
310
|
|
|
@@ -313,9 +320,12 @@ Search for tools using natural language queries. Works with both semantic (cloud
|
|
|
313
320
|
### Basic Usage
|
|
314
321
|
|
|
315
322
|
```python
|
|
323
|
+
import os
|
|
324
|
+
|
|
316
325
|
# Get a callable search tool
|
|
317
326
|
toolset = StackOneToolSet()
|
|
318
|
-
|
|
327
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
328
|
+
all_tools = toolset.fetch_tools(account_ids=[account_id])
|
|
319
329
|
search_tool = toolset.get_search_tool()
|
|
320
330
|
|
|
321
331
|
# Search for relevant tools — returns a Tools collection
|
|
@@ -327,15 +337,17 @@ tools[0](limit=10)
|
|
|
327
337
|
|
|
328
338
|
## Semantic Search
|
|
329
339
|
|
|
330
|
-
Discover tools using natural language instead of exact names. Queries like "onboard new hire" resolve to the right actions even when the tool is called `
|
|
340
|
+
Discover tools using natural language instead of exact names. Queries like "onboard new hire" resolve to the right actions even when the tool is called `workday_create_employee`.
|
|
331
341
|
|
|
332
342
|
```python
|
|
343
|
+
import os
|
|
333
344
|
from stackone_ai import StackOneToolSet
|
|
334
345
|
|
|
335
346
|
toolset = StackOneToolSet()
|
|
336
347
|
|
|
337
348
|
# Search by intent — returns Tools collection ready for any framework
|
|
338
|
-
|
|
349
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
350
|
+
tools = toolset.search_tools("manage employee records", account_ids=[account_id], top_k=5)
|
|
339
351
|
openai_tools = tools.to_openai()
|
|
340
352
|
|
|
341
353
|
# Lightweight: inspect results without fetching full tool definitions
|
|
@@ -357,19 +369,31 @@ tools = toolset.search_tools("manage employees", search="semantic")
|
|
|
357
369
|
tools = toolset.search_tools("manage employees", search="local")
|
|
358
370
|
```
|
|
359
371
|
|
|
360
|
-
Results are automatically scoped to connectors in your linked accounts. See [
|
|
372
|
+
Results are automatically scoped to connectors in your linked accounts. See [Search Tools Example](examples/search_tools.py) for `SearchTool` (`get_search_tool`) integration, OpenAI, and LangChain patterns.
|
|
361
373
|
|
|
362
374
|
## Examples
|
|
363
375
|
|
|
364
376
|
For more examples, check out the [examples/](examples/) directory:
|
|
365
377
|
|
|
366
|
-
- [
|
|
367
|
-
- [
|
|
368
|
-
- [
|
|
369
|
-
- [
|
|
370
|
-
- [
|
|
371
|
-
|
|
372
|
-
|
|
378
|
+
- [OpenAI Integration](examples/openai_integration.py) — OpenAI function calling
|
|
379
|
+
- [LangChain Integration](examples/langchain_integration.py) — LangChain tools
|
|
380
|
+
- [CrewAI Integration](examples/crewai_integration.py) — CrewAI agent
|
|
381
|
+
- [Search Tools](examples/search_tools.py) — Tool discovery (semantic, local, auto search)
|
|
382
|
+
- [Auth Management](examples/auth_management.py) — API key and account ID patterns
|
|
383
|
+
|
|
384
|
+
### Running Examples
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
# 1. Set up credentials
|
|
388
|
+
cp .env.example .env
|
|
389
|
+
# Edit .env with your API keys
|
|
390
|
+
|
|
391
|
+
# 2. Install dependencies
|
|
392
|
+
uv sync --all-extras
|
|
393
|
+
|
|
394
|
+
# 3. Run any example
|
|
395
|
+
uv run examples/search_tools.py
|
|
396
|
+
```
|
|
373
397
|
|
|
374
398
|
## Development
|
|
375
399
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Comprehensive auth management example showing all ways to configure API keys and account IDs.
|
|
3
|
+
|
|
4
|
+
```bash
|
|
5
|
+
uv run examples/auth_management.py
|
|
6
|
+
```
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from dotenv import load_dotenv
|
|
15
|
+
|
|
16
|
+
load_dotenv()
|
|
17
|
+
except ImportError:
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
from stackone_ai import StackOneToolSet
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def api_key_setup() -> None:
|
|
24
|
+
"""Demonstrate the two ways to provide an API key."""
|
|
25
|
+
print("\n--- API Key Setup ---")
|
|
26
|
+
|
|
27
|
+
# 1. Default: reads STACKONE_API_KEY from the environment
|
|
28
|
+
toolset_from_env = StackOneToolSet()
|
|
29
|
+
print("Created toolset from STACKONE_API_KEY env var (default)")
|
|
30
|
+
|
|
31
|
+
# 2. Explicit: pass the key directly
|
|
32
|
+
api_key = os.environ["STACKONE_API_KEY"]
|
|
33
|
+
toolset_explicit = StackOneToolSet(api_key=api_key)
|
|
34
|
+
print("Created toolset with explicit api_key")
|
|
35
|
+
|
|
36
|
+
# Both toolsets are functionally equivalent
|
|
37
|
+
print(f"Toolset from env: {toolset_from_env}")
|
|
38
|
+
print(f"Toolset from explicit: {toolset_explicit}")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def single_account(account_id: str) -> None:
|
|
42
|
+
"""Fetch tools scoped to a single account."""
|
|
43
|
+
print("\n--- Single Account via fetch_tools ---")
|
|
44
|
+
|
|
45
|
+
toolset = StackOneToolSet()
|
|
46
|
+
tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id])
|
|
47
|
+
print(f"Fetched {len(tools)} tools for configured account")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def set_accounts_globally(account_id: str) -> None:
|
|
51
|
+
"""Use set_accounts() to bind accounts at the toolset level."""
|
|
52
|
+
print("\n--- set_accounts() (global on toolset) ---")
|
|
53
|
+
|
|
54
|
+
toolset = StackOneToolSet()
|
|
55
|
+
toolset.set_accounts([account_id])
|
|
56
|
+
print("Set global accounts via set_accounts()")
|
|
57
|
+
|
|
58
|
+
tools = toolset.fetch_tools(actions=["workday_*"])
|
|
59
|
+
print(f"Fetched {len(tools)} tools (account inherited from toolset)")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def per_tool_override(account_id: str) -> None:
|
|
63
|
+
"""Override the account ID on a tools collection or an individual tool."""
|
|
64
|
+
print("\n--- Per-Tool Account Override ---")
|
|
65
|
+
|
|
66
|
+
toolset = StackOneToolSet()
|
|
67
|
+
tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id])
|
|
68
|
+
|
|
69
|
+
# Override on the entire tools collection
|
|
70
|
+
tools.set_account_id("overridden-account")
|
|
71
|
+
print("Called tools.set_account_id('overridden-account')")
|
|
72
|
+
|
|
73
|
+
# Override on a single tool
|
|
74
|
+
tool = tools.get_tool("workday_list_workers")
|
|
75
|
+
if tool:
|
|
76
|
+
tool.set_account_id("per-tool-account")
|
|
77
|
+
current = tool.get_account_id()
|
|
78
|
+
print(f"Single tool account_id is now: '{current}'")
|
|
79
|
+
else:
|
|
80
|
+
print("Tool 'workday_list_workers' not found -- skipping single-tool override")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def main() -> None:
|
|
84
|
+
api_key = os.getenv("STACKONE_API_KEY")
|
|
85
|
+
if not api_key:
|
|
86
|
+
print("STACKONE_API_KEY is not set. Please export it or add it to .env")
|
|
87
|
+
return
|
|
88
|
+
|
|
89
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
90
|
+
if not account_id:
|
|
91
|
+
print("Set STACKONE_ACCOUNT_ID to run this example.")
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
api_key_setup()
|
|
95
|
+
single_account(account_id)
|
|
96
|
+
set_accounts_globally(account_id)
|
|
97
|
+
per_tool_override(account_id)
|
|
98
|
+
|
|
99
|
+
print("\nAll auth management examples completed.")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
if __name__ == "__main__":
|
|
103
|
+
main()
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This example demonstrates how to use StackOne tools with CrewAI.
|
|
3
|
+
|
|
4
|
+
CrewAI uses LangChain tools natively.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
uv run examples/crewai_integration.py
|
|
8
|
+
```
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
from dotenv import load_dotenv
|
|
17
|
+
|
|
18
|
+
load_dotenv()
|
|
19
|
+
except ModuleNotFoundError:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
from crewai import Agent, Crew, Task
|
|
23
|
+
|
|
24
|
+
from stackone_ai import StackOneToolSet
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def crewai_integration():
|
|
28
|
+
account_id = os.getenv("STACKONE_ACCOUNT_ID")
|
|
29
|
+
if not os.getenv("STACKONE_API_KEY"):
|
|
30
|
+
print("Set STACKONE_API_KEY to run this example.")
|
|
31
|
+
return
|
|
32
|
+
if not account_id:
|
|
33
|
+
print("Set STACKONE_ACCOUNT_ID to run this example.")
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
toolset = StackOneToolSet()
|
|
37
|
+
tools = toolset.fetch_tools(
|
|
38
|
+
actions=["workday_list_workers", "workday_get_worker", "workday_get_current_user"],
|
|
39
|
+
account_ids=[account_id],
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# CrewAI uses LangChain tools natively
|
|
43
|
+
langchain_tools = tools.to_langchain()
|
|
44
|
+
print(f"Loaded {len(langchain_tools)} tools for CrewAI.")
|
|
45
|
+
|
|
46
|
+
agent = Agent(
|
|
47
|
+
role="HR Manager",
|
|
48
|
+
goal="List the first 5 employees in the company",
|
|
49
|
+
backstory="With over 10 years of experience in HR and employee management, "
|
|
50
|
+
"you excel at finding patterns in complex datasets.",
|
|
51
|
+
llm="gpt-5.4",
|
|
52
|
+
tools=langchain_tools,
|
|
53
|
+
max_iter=2,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
task = Task(
|
|
57
|
+
description="List the first 5 employees in the company",
|
|
58
|
+
agent=agent,
|
|
59
|
+
expected_output="A list of the first 5 employees with their details",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
crew = Crew(agents=[agent], tasks=[task])
|
|
63
|
+
|
|
64
|
+
result = crew.kickoff()
|
|
65
|
+
print(f"Crew result:\n{result}")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if __name__ == "__main__":
|
|
69
|
+
crewai_integration()
|