Skip to content

feat(stackone): add StackOne AI integration#3

Merged
shashi-stackone merged 34 commits into
mainfrom
ENG-10848-try-to-get-listed-as-third-party-toolset-on-pydantic
Apr 23, 2026
Merged

feat(stackone): add StackOne AI integration#3
shashi-stackone merged 34 commits into
mainfrom
ENG-10848-try-to-get-listed-as-third-party-toolset-on-pydantic

Conversation

@ryoppippi

@ryoppippi ryoppippi commented Jan 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Add StackOne AI integration enabling AI agents to access 200+ SaaS integrations (HRIS, ATS, LMS, CRM, IAM, etc.) through a unified API.

Changes

  • Add tool_from_stackone() for individual tool integration
  • Add StackOneToolset for bulk registration with glob pattern filtering
  • Add comprehensive unit tests with 100% coverage
  • Add documentation and usage examples

New Files

  • pydantic_ai_slim/pydantic_ai/ext/stackone.py - Core integration module
  • tests/test_ext_stackone.py - Unit tests
  • examples/stackone_integration.py - Usage examples

Documentation Updates

  • docs/install.md - Added stackone extra
  • docs/third-party-tools.md - Added StackOne tools section
  • docs/toolsets.md - Added StackOne toolset section

Dependencies

  • stackone-ai>=2.1.1 (requires Python 3.10+, same as Pydantic AI)

Test plan

  • Unit tests pass (uv run pytest tests/test_ext_stackone.py)
  • StackOne-specific pyright check passes
  • Pre-commit checks pass (except existing upstream pyright issues unrelated to this PR)

Jira: ENG-10848

Add integration with StackOne unified API platform for HRIS, ATS, CRM,
and other business systems.

- Add `tool_from_stackone()` for single tool creation
- Add `StackOneToolset` for bulk tool registration with pattern matching
- Require stackone-ai>=2.1.1 (Python 3.10+)
- Add documentation and examples
- Add comprehensive unit tests with 100% coverage
@ryoppippi ryoppippi force-pushed the ENG-10848-try-to-get-listed-as-third-party-toolset-on-pydantic branch from d77e04f to 888b2d4 Compare January 22, 2026 11:26
@ryoppippi ryoppippi changed the title feat: add StackOne AI integration for Pydantic AI feat(stackone): add StackOne AI integration Jan 22, 2026
- Fix StackOne URL from .co to .com
- Update description to reflect current positioning as "AI Integration Gateway"
Comment thread docs/toolsets.md Outdated
Comment thread docs/toolsets.md Outdated

@glebedel glebedel left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should update the examples but also add the meta tools! That would be a great value-add and differentiator for pydantic too because they might not have this concept at all.

eg. via import search_tool & execute_tool and that could take any tools, stackone tools for sure but also any other pydantic tools (eg. let's say the exa one)

Comment thread examples/stackone_integration.py Outdated
Comment thread docs/third-party-tools.md Outdated
Comment thread docs/third-party-tools.md Outdated
Add search_tool, execute_tool, and feedback_tool functions that wrap
StackOne's utility tools API (tool_search, tool_execute, tool_feedback).

Extend StackOneToolset with new options:
- include_utility_tools: enables dynamic tool discovery mode
- include_feedback_tool: adds feedback collection capability
- hybrid_alpha: configures BM25/TF-IDF search weight

Update documentation and examples to reflect the new API.
Update minimum version requirement to 2.3.0 which includes the
utility_tools API (tool_search, tool_execute, tool_feedback).
- Update StackOneToolset tests to match new implementation that uses
  _tool_from_stackone_tool directly instead of tool_from_stackone
- Add test for include_utility_tools option
- Mark docstring examples with test="skip" to avoid linting issues
- Remove `{test="skip"}` from docstring examples
- Simplify StackOneToolset example to match ExaToolset pattern
- Move Args documentation from class docstring to __init__ method
- Remove verbose examples from search_tool, execute_tool, feedback_tool
- Fix pyright type error in test file with ignore comment
- Replace hris_* with stackone_* in filter_pattern example
- Replace hris_list_employees/hris_get_employee with stackone_* tools
- Update description to remove 'unified interface' terminology
…_*/stackone_*

Per PR review feedback, update all examples and tests to use actual StackOne
provider naming patterns like 'bamboohr_*' and 'workday_*' instead of
fictional 'hris_*' or 'stackone_*' patterns.

- Update docs/toolsets.md examples
- Update docs/third-party-tools.md examples
- Update examples/stackone_integration.py
- Update tests/test_ext_stackone.py
- Update docstrings in pydantic_ai_slim/pydantic_ai/ext/stackone.py
@ryoppippi ryoppippi requested a review from glebedel January 30, 2026 15:53
- Format test file with ruff to fix line length issues
- Add {test="skip"} to StackOneToolset docstring example to skip
  example test that requires stackone-ai package
Add stackone.py and test_ext_stackone.py to coverage omit list,
similar to aci.py and exa.py which are also external integrations.
@glebedel glebedel requested a review from Shashikant86 February 3, 2026 11:31
@shashi-stackone shashi-stackone requested review from shashi-stackone and removed request for Shashikant86 February 23, 2026 16:03
@shashi-stackone

Copy link
Copy Markdown
Contributor

Managed to get the CI passing now also noticed that in the Docs we are adding too many tools strategies there.

@glebedel Comparing to the others they just added how to use a toolset and multiple tools and thats's it .. having the Dynamic Discovery, Feedback and Search (semantic/lexical) would be great but we are adding too much on the page in the docs.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 4 files (changes from recent commits).

Requires human review: Adding a new third-party integration (StackOne) is a significant feature addition that requires human review for architectural alignment and maintenance considerations.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="pydantic_ai_slim/pydantic_ai/ext/stackone.py">

<violation number="1" location="pydantic_ai_slim/pydantic_ai/ext/stackone.py:117">
P2: Detect `execute_config["account_ids"]` by key presence, not truthiness, so mutual-exclusion and resolution logic work correctly for falsy values.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread pydantic_ai_slim/pydantic_ai/ext/stackone.py Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

Comment thread docs/third-party-tools.md Outdated

## StackOne Tools {#stackone-tools}

[StackOne](https://www.stackone.com) is Integration Infrastructure for AI Agents, providing tools for 200+ enterprise applications. If you'd like to use a StackOne tool with Pydantic AI, you can use the [`tool_from_stackone`][pydantic_ai.ext.stackone.tool_from_stackone] convenience method. You will need to install the `stackone-ai` package (requires Python 3.10+), set `STACKONE_API_KEY` in your environment, and provide one or more connected account IDs via `STACKONE_ACCOUNT_ID` or by passing `account_ids=...` directly (a single string or a list).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't account_ids optional?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need users to sets STACKONE_ACCOUNT_ID or pass account_ids either single or multiple IDS .. I think only API Key is not enough we need account ID(s) .. I think, you question is to rephrase the docs? as at the moment it sounds like account_ids are required?

Comment thread docs/third-party-tools.md Outdated
Comment on lines +111 to +127
worker_tool = tool_from_stackone('workday_list_workers')

agent = Agent('openai:gpt-5.4', tools=[worker_tool])

result = agent.run_sync('List the first 5 workers')
print(result.output)
```

For multiple StackOne tools, use the [`StackOneToolset`][pydantic_ai.ext.stackone.StackOneToolset] [toolset](toolsets.md#stackone-tools):

```python {test="skip"}
from pydantic_ai import Agent
from pydantic_ai.ext.stackone import StackOneToolset

toolset = StackOneToolset(filter_pattern='workday_list_worker*')

agent = Agent('openai:gpt-5.4', toolsets=[toolset])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are these the first examples that we want to expose?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, it used to be bamboohr, I changes it to Workday .. Or do you want it to be more simplified example? I added filter pattern as Workday returns more than 128 tools which is limit for OpenAI Specs .. Should we change example or how we represent it?

Comment thread docs/third-party-tools.md Outdated
Comment on lines +158 to +165
=== "Search & Execute"

The agent receives two meta tools, `tool_search` and `tool_execute`. The model calls `tool_search` with a natural-language query (e.g. `"list employees"`), picks a result, and calls `tool_execute` with the tool name and parameters. Prompt size stays constant regardless of catalog size. Requires `stackone-ai >= 2.5.0`.

```python {test="skip"}
toolset = StackOneToolset(mode='search_and_execute')
agent = Agent('openai:gpt-5.4', toolsets=[toolset])
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feel like it's confusing to have search as well as search_and_execute suggested - in which case should they use each should be described or we should expose one?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondered about this as well.. Should we just show search tools for now and remove the search_and_execute for now? Or just hide from docs? Or recommend user which one to use in what situation by updating doc providing more context?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pydantic also have own Tool Search so I thought having execute will be good but wasn't sure.

@shashi-stackone

Copy link
Copy Markdown
Contributor

Discussed with @willleeney and decided we have search and execute there with other strategies demonstrated so keep it minimal
I created Tools, Search and Execute and Multiple Account (3 tabs not 4) that covers all possibilities

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docs/third-party-tools.md">

<violation number="1" location="docs/third-party-tools.md:137">
P3: The example comment says this is a single-tool setup without a toolset, but the code still passes `toolsets=[toolset]`. Make the code match the documented usage.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread docs/third-party-tools.md
# Or a single tool without a toolset
worker_tool = tool_from_stackone('workday_list_workers')

agent = Agent('openai:gpt-5.4', toolsets=[toolset], tools=[worker_tool])

@cubic-dev-ai cubic-dev-ai Bot Apr 21, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The example comment says this is a single-tool setup without a toolset, but the code still passes toolsets=[toolset]. Make the code match the documented usage.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docs/third-party-tools.md, line 137:

<comment>The example comment says this is a single-tool setup without a toolset, but the code still passes `toolsets=[toolset]`. Make the code match the documented usage.</comment>

<file context>
@@ -102,68 +102,62 @@ agent = Agent('openai:gpt-5.2', toolsets=[toolset])
-        search='auto',
-    )
-    agent = Agent('openai:gpt-5.4', toolsets=[toolset])
+    agent = Agent('openai:gpt-5.4', toolsets=[toolset], tools=[worker_tool])
     ```
 
</file context>
Suggested change
agent = Agent('openai:gpt-5.4', toolsets=[toolset], tools=[worker_tool])
agent = Agent('openai:gpt-5.4', tools=[worker_tool])
Fix with Cubic

@cubic-dev-ai

cubic-dev-ai Bot commented Apr 23, 2026

Copy link
Copy Markdown

You're iterating quickly on this pull request. To help protect your rate limits, cubic has paused automatic reviews on new pushes for now—when you're ready for another review, comment @cubic-dev-ai review.

Comment thread docs/third-party-tools.md Outdated
```

!!! note
Bare `StackOneToolset()` loads every tool for your connected account(s). Large catalogs may exceed the model's per-request tool-count limit — narrow with `tools=` or `filter_pattern=`, or use `mode='search_and_execute'` for on-demand discovery.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest search_and_execute as the first option. Also link to where the examples for each are given?

Comment thread docs/third-party-tools.md Outdated
!!! note
Bare `StackOneToolset()` loads every tool for your connected account(s). Large catalogs may exceed the model's per-request tool-count limit — narrow with `tools=` or `filter_pattern=`, or use `mode='search_and_execute'` for on-demand discovery.

For more control, narrow the toolset, use meta-tools for large catalogs, or connect multiple accounts:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't be using meta-tools anymore

Comment thread docs/third-party-tools.md
# Or a single tool without a toolset
worker_tool = tool_from_stackone('workday_list_workers')

agent = Agent('openai:gpt-5.4', toolsets=[toolset], tools=[worker_tool])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would say explicitly that you can use both in combination as well

Comment thread docs/third-party-tools.md Outdated

=== "Search & Execute"

The agent receives two meta tools, `tool_search` and `tool_execute`. The model decides the search query at runtime, picks a result, and calls `tool_execute` with the tool name and parameters. Prompt size stays constant regardless of catalog size. Requires `stackone-ai >= 2.5.0`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say "instead of giving every tool available, we can only expose two tools ... " to make it obvious what is going on

Comment thread docs/third-party-tools.md Outdated

=== "Search & Execute"

The agent receives two meta tools, `tool_search` and `tool_execute`. The model decides the search query at runtime, picks a result, and calls `tool_execute` with the tool name and parameters. Prompt size stays constant regardless of catalog size. Requires `stackone-ai >= 2.5.0`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also I would have something here written that semantic calls our api for a model for doing the search whereas local uses BM-25 to do the search to explicitly define the difference between what local and non-local actually means

Comment thread docs/third-party-tools.md Outdated
agent = Agent('openai:gpt-5.4', toolsets=[toolset])
```

`search_config['method']` picks the strategy: `auto` (default, tries semantic then falls back to local), `semantic` (LLM-powered embedding search only), or `local` (on-device BM25+TF-IDF).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it BM-25 + TF-IDF still or isn't it just BM-25?

but also do the written stuff about the description before you show the code of how to do it

@shashi-stackone

Copy link
Copy Markdown
Contributor

Thank @willleeney for feedback on the docs .. Agreed on all the points and made changes accordingly ..

@glebedel glebedel self-requested a review April 23, 2026 13:29

@glebedel glebedel left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@shashi-stackone shashi-stackone merged commit 332fa2f into main Apr 23, 2026
29 of 39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants