stackone-ai 2.6.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.
Files changed (188) hide show
  1. stackone_ai-2.8.0/.env.example +6 -0
  2. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.gitignore +1 -0
  3. stackone_ai-2.8.0/.release-please-manifest.json +3 -0
  4. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/CHANGELOG.md +14 -0
  5. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/PKG-INFO +57 -32
  6. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/README.md +52 -28
  7. stackone_ai-2.8.0/examples/auth_management.py +103 -0
  8. stackone_ai-2.8.0/examples/crewai_integration.py +69 -0
  9. stackone_ai-2.8.0/examples/langchain_integration.py +69 -0
  10. stackone_ai-2.8.0/examples/langgraph_integration.py +62 -0
  11. stackone_ai-2.8.0/examples/openai_integration.py +113 -0
  12. stackone_ai-2.8.0/examples/pydantic_ai_integration.py +65 -0
  13. stackone_ai-2.8.0/examples/search_tools.py +171 -0
  14. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/examples/test_examples.py +4 -7
  15. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/justfile +4 -0
  16. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/pyproject.toml +5 -4
  17. stackone_ai-2.8.0/scripts/benchmark_search.py +134 -0
  18. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/__init__.py +1 -1
  19. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/toolset.py +42 -11
  20. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/tests/test_agent_tools.py +7 -2
  21. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/tests/test_fetch_tools.py +222 -0
  22. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/uv.lock +1384 -473
  23. stackone_ai-2.6.0/.release-please-manifest.json +0 -3
  24. stackone_ai-2.6.0/examples/agent_tool_search.py +0 -202
  25. stackone_ai-2.6.0/examples/crewai_integration.py +0 -55
  26. stackone_ai-2.6.0/examples/file_uploads.py +0 -83
  27. stackone_ai-2.6.0/examples/index.py +0 -105
  28. stackone_ai-2.6.0/examples/langchain_integration.py +0 -51
  29. stackone_ai-2.6.0/examples/openai_integration.py +0 -93
  30. stackone_ai-2.6.0/examples/search_tool_example.py +0 -66
  31. stackone_ai-2.6.0/examples/semantic_search_example.py +0 -423
  32. stackone_ai-2.6.0/examples/stackone_account_ids.py +0 -40
  33. stackone_ai-2.6.0/examples/workday_integration.py +0 -91
  34. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.claude/rules/development-workflow.md +0 -0
  35. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.claude/rules/examples-standards.md +0 -0
  36. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.claude/rules/git-workflow.md +0 -0
  37. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.claude/rules/nix-workflow.md +0 -0
  38. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.claude/rules/no-relative-imports.md +0 -0
  39. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.claude/rules/package-installation.md +0 -0
  40. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.claude/rules/release-please-standards.md +0 -0
  41. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.claude/rules/uv-scripts.md +0 -0
  42. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.cursor/rules/development-workflow.mdc +0 -0
  43. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.cursor/rules/examples-standards.mdc +0 -0
  44. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.cursor/rules/git-workflow.mdc +0 -0
  45. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.cursor/rules/no-relative-imports.mdc +0 -0
  46. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.cursor/rules/package-installation.mdc +0 -0
  47. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.cursor/rules/release-please-standards.mdc +0 -0
  48. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.cursor/rules/uv-scripts.mdc +0 -0
  49. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.envrc +0 -0
  50. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.github/actions/setup-nix/action.yaml +0 -0
  51. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.github/dependabot.yaml +0 -0
  52. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.github/workflows/ci.yaml +0 -0
  53. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.github/workflows/nix-flake-update.yaml +0 -0
  54. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.github/workflows/nix-flake.yaml +0 -0
  55. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.github/workflows/release.yaml +0 -0
  56. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.gitleaks.toml +0 -0
  57. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.gitmodules +0 -0
  58. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.mcp.json +0 -0
  59. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/.release-please-config.json +0 -0
  60. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/CLAUDE.md +0 -0
  61. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/LICENSE +0 -0
  62. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/flake.lock +0 -0
  63. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/flake.nix +0 -0
  64. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/constants.py +0 -0
  65. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/feedback/__init__.py +0 -0
  66. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/feedback/tool.py +0 -0
  67. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/integrations/__init__.py +0 -0
  68. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/integrations/langgraph.py +0 -0
  69. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/local_search.py +0 -0
  70. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/models.py +0 -0
  71. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/py.typed +0 -0
  72. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/semantic_search.py +0 -0
  73. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/utils/__init__.py +0 -0
  74. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/utils/normalize.py +0 -0
  75. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/stackone_ai/utils/tfidf_index.py +0 -0
  76. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/tests/conftest.py +0 -0
  77. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/tests/mocks/serve.ts +0 -0
  78. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/tests/test_feedback.py +0 -0
  79. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/tests/test_integrations_langgraph.py +0 -0
  80. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/tests/test_local_search.py +0 -0
  81. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/tests/test_models.py +0 -0
  82. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/tests/test_semantic_search.py +0 -0
  83. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/tests/test_tfidf_index.py +0 -0
  84. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/tests/test_tool_calling.py +0 -0
  85. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/tests/test_toolset.py +0 -0
  86. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/rules/development-workflow.md +0 -0
  87. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/rules/file-operations.md +0 -0
  88. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/rules/git-workflow.md +0 -0
  89. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/rules/pnpm-usage.md +0 -0
  90. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/rules/typescript-patterns.md +0 -0
  91. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/rules/typescript-testing.md +0 -0
  92. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.claude/skills/orama-integration/SKILL.md +0 -0
  93. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/development-workflow.mdc +0 -0
  94. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/file-operations.mdc +0 -0
  95. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/git-workflow.mdc +0 -0
  96. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/orama-integration.mdc +0 -0
  97. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/pnpm-usage.mdc +0 -0
  98. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/typescript-patterns.mdc +0 -0
  99. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.cursor/rules/typescript-testing.mdc +0 -0
  100. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.envrc +0 -0
  101. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.git +0 -0
  102. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/CODEOWNERS +0 -0
  103. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/actions/setup-nix/action.yaml +0 -0
  104. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/workflows/check-title.yaml +0 -0
  105. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/workflows/ci.yaml +0 -0
  106. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/workflows/claude.yaml +0 -0
  107. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/workflows/dry-publish.yaml +0 -0
  108. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/workflows/nix-flake.yaml +0 -0
  109. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.github/workflows/release.yaml +0 -0
  110. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.gitignore +0 -0
  111. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.gitleaks.toml +0 -0
  112. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.mcp.json +0 -0
  113. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.oxfmtrc.jsonc +0 -0
  114. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/.oxlintrc.jsonc +0 -0
  115. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/AGENTS.md +0 -0
  116. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/CHANGELOG.md +0 -0
  117. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/CLAUDE.md +0 -0
  118. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/LICENSE +0 -0
  119. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/README.md +0 -0
  120. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/README.md +0 -0
  121. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/ai-sdk-integration.test.ts +0 -0
  122. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/ai-sdk-integration.ts +0 -0
  123. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/anthropic-integration.ts +0 -0
  124. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/claude-agent-sdk-integration.test.ts +0 -0
  125. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/claude-agent-sdk-integration.ts +0 -0
  126. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/fetch-tools-debug.ts +0 -0
  127. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/fetch-tools.test.ts +0 -0
  128. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/fetch-tools.ts +0 -0
  129. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/meta-tools.ts +0 -0
  130. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/openai-integration.test.ts +0 -0
  131. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/openai-integration.ts +0 -0
  132. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/openai-responses-integration.test.ts +0 -0
  133. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/openai-responses-integration.ts +0 -0
  134. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/package.json +0 -0
  135. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/tanstack-ai-integration.test.ts +0 -0
  136. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/tanstack-ai-integration.ts +0 -0
  137. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/examples/tsconfig.json +0 -0
  138. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/flake.lock +0 -0
  139. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/flake.nix +0 -0
  140. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/knip.config.ts +0 -0
  141. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/lefthook.yaml +0 -0
  142. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.example-api.ts +0 -0
  143. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.mcp.ts +0 -0
  144. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.openai.ts +0 -0
  145. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.stackone-ai.ts +0 -0
  146. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.stackone-rpc.ts +0 -0
  147. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.ts +0 -0
  148. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/handlers.utils.ts +0 -0
  149. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/mcp-server.ts +0 -0
  150. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/mocks/node.ts +0 -0
  151. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/package.json +0 -0
  152. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/pnpm-lock.yaml +0 -0
  153. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/pnpm-workspace.yaml +0 -0
  154. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/consts.ts +0 -0
  155. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/feedback.test.ts +0 -0
  156. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/feedback.ts +0 -0
  157. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/headers.test.ts +0 -0
  158. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/headers.ts +0 -0
  159. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/index.ts +0 -0
  160. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/mcp-client.test.ts +0 -0
  161. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/mcp-client.ts +0 -0
  162. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/requestBuilder.test.ts +0 -0
  163. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/requestBuilder.ts +0 -0
  164. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/rpc-client.test.ts +0 -0
  165. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/rpc-client.ts +0 -0
  166. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/schema.ts +0 -0
  167. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/tool.test-d.ts +0 -0
  168. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/tool.test.ts +0 -0
  169. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/tool.ts +0 -0
  170. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/toolsets.test-d.ts +0 -0
  171. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/toolsets.test.ts +0 -0
  172. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/toolsets.ts +0 -0
  173. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/types.ts +0 -0
  174. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/array.test.ts +0 -0
  175. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/array.ts +0 -0
  176. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/error-stackone-api.test.ts +0 -0
  177. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/error-stackone-api.ts +0 -0
  178. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/error-stackone.test.ts +0 -0
  179. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/error-stackone.ts +0 -0
  180. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/tfidf-index.test.ts +0 -0
  181. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/tfidf-index.ts +0 -0
  182. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/try-import.test.ts +0 -0
  183. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/try-import.ts +0 -0
  184. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/src/utils/type.ts +0 -0
  185. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/tsconfig.json +0 -0
  186. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/tsdown.config.ts +0 -0
  187. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/vitest.config.ts +0 -0
  188. {stackone_ai-2.6.0 → stackone_ai-2.8.0}/vendor/stackone-ai-node/vitest.setup.ts +0 -0
@@ -0,0 +1,6 @@
1
+ # Required for all examples
2
+ STACKONE_API_KEY=your-stackone-api-key
3
+ STACKONE_ACCOUNT_ID=your-account-id
4
+
5
+ # Required for OpenAI-based examples (openai_integration, langchain_integration, crewai_integration, search_tools)
6
+ OPENAI_API_KEY=your-openai-api-key
@@ -1,5 +1,6 @@
1
1
  .env
2
2
  .env.*
3
+ !.env.example
3
4
  .venv
4
5
 
5
6
  .pytest_cache
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "2.8.0"
3
+ }
@@ -1,5 +1,19 @@
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
+
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)
11
+
12
+
13
+ ### Features
14
+
15
+ * **search-optimization:** cache tool catalog and parallelize per-account MCP fetches ([#173](https://github.com/StackOneHQ/stackone-ai-python/issues/173)) ([cd635e6](https://github.com/StackOneHQ/stackone-ai-python/commit/cd635e65621e4e84da270a57e4e1453a3734ad95))
16
+
3
17
  ## [2.6.0](https://github.com/StackOneHQ/stackone-ai-python/compare/stackone-ai-v2.5.1...stackone-ai-v2.6.0) (2026-04-07)
4
18
 
5
19
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stackone-ai
3
- Version: 2.6.0
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>=0.3.6; extra == 'examples'
26
- Requires-Dist: langgraph>=0.2.0; extra == 'examples'
27
- Requires-Dist: openai>=1.63.2; extra == 'examples'
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 with API key
90
- toolset = StackOneToolSet() # Uses STACKONE_API_KEY env var
91
- # Or explicitly: toolset = StackOneToolSet(api_key="your-api-key")
91
+ # Initialize — reads STACKONE_API_KEY from environment
92
+ toolset = StackOneToolSet()
92
93
 
93
- # Get HRIS-related tools with glob patterns
94
- tools = toolset.fetch_tools(actions=["bamboohr_*"], account_ids=["your-account-id"])
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("bamboohr_get_employee")
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", "bamboohr"])
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", "bamboohr"]`). Case-insensitive matching.
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: `["bamboohr_list_employees"]`
145
+ - Exact match: `["workday_list_workers"]`
144
146
  - Glob pattern: `["*_list_employees"]` matches all tools ending with `_list_employees`
145
- - Provider prefix: `["bamboohr_*"]` matches all BambooHR tools
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
- tools = toolset.fetch_tools(actions=["bamboohr_*"], account_ids=["your-account-id"])
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-4o-mini")
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
- tools = toolset.fetch_tools(actions=["bamboohr_*"], account_ids=["your-account-id"])
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-4o-mini")
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
- tools = toolset.fetch_tools(actions=["bamboohr_*"], account_ids=["your-account-id"])
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-4o-mini"
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=["bamboohr_list_employees", "bamboohr_get_employee"]
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
- all_tools = toolset.fetch_tools(account_ids=["your-account-id"])
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 `bamboohr_create_employee`.
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
- tools = toolset.search_tools("manage employee records", account_ids=["your-account-id"], top_k=5)
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 [Semantic Search Example](examples/semantic_search_example.py) for `SearchTool` (`get_search_tool`) integration, OpenAI, and LangChain patterns.
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
- - [StackOne Account IDs](examples/stackone_account_ids.py)
399
- - [File Uploads](examples/file_uploads.py)
400
- - [OpenAI Integration](examples/openai_integration.py)
401
- - [LangChain Integration](examples/langchain_integration.py)
402
- - [CrewAI Integration](examples/crewai_integration.py)
403
- - [Search Tool](examples/search_tool_example.py)
404
- - [Semantic Search](examples/semantic_search_example.py)
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 with API key
58
- toolset = StackOneToolSet() # Uses STACKONE_API_KEY env var
59
- # Or explicitly: toolset = StackOneToolSet(api_key="your-api-key")
58
+ # Initialize — reads STACKONE_API_KEY from environment
59
+ toolset = StackOneToolSet()
60
60
 
61
- # Get HRIS-related tools with glob patterns
62
- tools = toolset.fetch_tools(actions=["bamboohr_*"], account_ids=["your-account-id"])
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("bamboohr_get_employee")
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", "bamboohr"])
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", "bamboohr"]`). Case-insensitive matching.
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: `["bamboohr_list_employees"]`
112
+ - Exact match: `["workday_list_workers"]`
112
113
  - Glob pattern: `["*_list_employees"]` matches all tools ending with `_list_employees`
113
- - Provider prefix: `["bamboohr_*"]` matches all BambooHR tools
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
- tools = toolset.fetch_tools(actions=["bamboohr_*"], account_ids=["your-account-id"])
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-4o-mini")
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
- tools = toolset.fetch_tools(actions=["bamboohr_*"], account_ids=["your-account-id"])
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-4o-mini")
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
- tools = toolset.fetch_tools(actions=["bamboohr_*"], account_ids=["your-account-id"])
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-4o-mini"
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=["bamboohr_list_employees", "bamboohr_get_employee"]
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
- all_tools = toolset.fetch_tools(account_ids=["your-account-id"])
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 `bamboohr_create_employee`.
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
- tools = toolset.search_tools("manage employee records", account_ids=["your-account-id"], top_k=5)
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 [Semantic Search Example](examples/semantic_search_example.py) for `SearchTool` (`get_search_tool`) integration, OpenAI, and LangChain patterns.
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
- - [StackOne Account IDs](examples/stackone_account_ids.py)
367
- - [File Uploads](examples/file_uploads.py)
368
- - [OpenAI Integration](examples/openai_integration.py)
369
- - [LangChain Integration](examples/langchain_integration.py)
370
- - [CrewAI Integration](examples/crewai_integration.py)
371
- - [Search Tool](examples/search_tool_example.py)
372
- - [Semantic Search](examples/semantic_search_example.py)
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()