-
Notifications
You must be signed in to change notification settings - Fork 0
feat(examples): streamline examples, standardize auth patterns and migrate examples to Workday #179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
85db80f
Example Cleanup - Python
shashi-stackone 66ca944
Fix Linter issue
shashi-stackone 23d0fe8
Remove example readme
shashi-stackone 04b723c
Address the PR comment
shashi-stackone 2a1df88
Add Pydantic and Langgraph examples in the from docs
shashi-stackone 02f7396
Lower the CrewAI version and Update Pydantic AI example to use public…
shashi-stackone 933cd10
Update Pydantic Example
shashi-stackone File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # Required for all examples | ||
| STACKONE_API_KEY=your-stackone-api-key | ||
| STACKONE_ACCOUNT_ID=your-account-id | ||
|
|
||
| # Required for OpenAI-based examples (openai_integration, langchain_integration, crewai_integration, search_tools) | ||
| OPENAI_API_KEY=your-openai-api-key |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| .env | ||
| .env.* | ||
| !.env.example | ||
| .venv | ||
|
|
||
| .pytest_cache | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,17 +52,18 @@ uv add 'stackone-ai[mcp,examples]' | |
| ## Quick Start | ||
|
|
||
| ```python | ||
| import os | ||
| from stackone_ai import StackOneToolSet | ||
|
|
||
| # Initialize with API key | ||
| toolset = StackOneToolSet() # Uses STACKONE_API_KEY env var | ||
| # Or explicitly: toolset = StackOneToolSet(api_key="your-api-key") | ||
| # Initialize — reads STACKONE_API_KEY from environment | ||
| toolset = StackOneToolSet() | ||
|
|
||
| # Get HRIS-related tools with glob patterns | ||
| tools = toolset.fetch_tools(actions=["bamboohr_*"], account_ids=["your-account-id"]) | ||
| # Fetch tools — pass account ID from STACKONE_ACCOUNT_ID env var | ||
| account_id = os.getenv("STACKONE_ACCOUNT_ID") | ||
| tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id]) | ||
|
|
||
| # Use a specific tool with the call method | ||
| employee_tool = tools.get_tool("bamboohr_get_employee") | ||
| employee_tool = tools.get_tool("workday_get_worker") | ||
| # Call with keyword arguments | ||
| employee = employee_tool.call(id="employee-id") | ||
| # Or with traditional execute method | ||
|
|
@@ -86,7 +87,7 @@ toolset = StackOneToolSet() | |
| tools = toolset.fetch_tools(account_ids=["acc-123", "acc-456"]) | ||
|
|
||
| # Filter by providers (case-insensitive) | ||
| tools = toolset.fetch_tools(providers=["hibob", "bamboohr"]) | ||
| tools = toolset.fetch_tools(providers=["hibob", "workday"]) | ||
|
|
||
| # Filter by action patterns with glob support | ||
| tools = toolset.fetch_tools(actions=["*_list_employees"]) | ||
|
|
@@ -106,11 +107,11 @@ tools = toolset.fetch_tools(providers=["hibob"]) | |
| **Filtering Options:** | ||
|
|
||
| - **`account_ids`**: Filter tools by account IDs. Tools will be loaded for each specified account. | ||
| - **`providers`**: Filter by provider names (e.g., `["hibob", "bamboohr"]`). Case-insensitive matching. | ||
| - **`providers`**: Filter by provider names (e.g., `["hibob", "workday"]`). Case-insensitive matching. | ||
| - **`actions`**: Filter by action patterns with glob support: | ||
| - Exact match: `["bamboohr_list_employees"]` | ||
| - Exact match: `["workday_list_workers"]` | ||
| - Glob pattern: `["*_list_employees"]` matches all tools ending with `_list_employees` | ||
| - Provider prefix: `["bamboohr_*"]` matches all BambooHR tools | ||
| - Provider prefix: `["workday_*"]` matches all Workday tools | ||
|
|
||
| ## Implicit Feedback (Beta) | ||
|
|
||
|
|
@@ -165,18 +166,20 @@ When two calls for the same session happen within a few seconds, the SDK emits a | |
| StackOne tools work seamlessly with LangChain, enabling powerful AI agent workflows: | ||
|
|
||
| ```python | ||
| import os | ||
| from langchain_openai import ChatOpenAI | ||
| from stackone_ai import StackOneToolSet | ||
|
|
||
| # Initialize StackOne tools | ||
| toolset = StackOneToolSet() | ||
| tools = toolset.fetch_tools(actions=["bamboohr_*"], account_ids=["your-account-id"]) | ||
| account_id = os.getenv("STACKONE_ACCOUNT_ID") | ||
| tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id]) | ||
|
|
||
| # Convert to LangChain format | ||
| langchain_tools = tools.to_langchain() | ||
|
|
||
| # Use with LangChain models | ||
| model = ChatOpenAI(model="gpt-4o-mini") | ||
| model = ChatOpenAI(model="gpt-5.4") | ||
| model_with_tools = model.bind_tools(langchain_tools) | ||
|
|
||
| # Execute AI-driven tool calls | ||
|
|
@@ -204,6 +207,7 @@ pip install langgraph langchain-openai | |
| ``` | ||
|
|
||
| ```python | ||
| import os | ||
| from langchain_openai import ChatOpenAI | ||
| from typing import Annotated | ||
| from typing_extensions import TypedDict | ||
|
|
@@ -217,7 +221,8 @@ from stackone_ai.integrations.langgraph import to_tool_node, bind_model_with_too | |
|
|
||
| # Prepare tools | ||
| toolset = StackOneToolSet() | ||
| tools = toolset.fetch_tools(actions=["bamboohr_*"], account_ids=["your-account-id"]) | ||
| account_id = os.getenv("STACKONE_ACCOUNT_ID") | ||
| tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id]) | ||
| langchain_tools = tools.to_langchain() | ||
|
|
||
| class State(TypedDict): | ||
|
|
@@ -228,7 +233,7 @@ graph = StateGraph(State) | |
| graph.add_node("tools", to_tool_node(langchain_tools)) | ||
|
|
||
| def call_llm(state: dict): | ||
| llm = ChatOpenAI(model="gpt-4o-mini") | ||
| llm = ChatOpenAI(model="gpt-5.4") | ||
| llm = bind_model_with_tools(llm, langchain_tools) | ||
| resp = llm.invoke(state["messages"]) # returns AIMessage with optional tool_calls | ||
| return {"messages": state["messages"] + [resp]} | ||
|
|
@@ -250,12 +255,14 @@ _ = app.invoke({"messages": [("user", "Get employee with id emp123") ]}) | |
| CrewAI uses LangChain tools natively, making integration seamless: | ||
|
|
||
| ```python | ||
| import os | ||
| from crewai import Agent, Crew, Task | ||
| from stackone_ai import StackOneToolSet | ||
|
|
||
| # Get tools and convert to LangChain format | ||
| toolset = StackOneToolSet() | ||
| tools = toolset.fetch_tools(actions=["bamboohr_*"], account_ids=["your-account-id"]) | ||
| account_id = os.getenv("STACKONE_ACCOUNT_ID") | ||
| tools = toolset.fetch_tools(actions=["workday_*"], account_ids=[account_id]) | ||
| langchain_tools = tools.to_langchain() | ||
|
|
||
| # Create CrewAI agent with StackOne tools | ||
|
|
@@ -264,7 +271,7 @@ agent = Agent( | |
| goal="Analyze employee data and generate insights", | ||
| backstory="Expert in HR analytics and employee management", | ||
| tools=langchain_tools, | ||
| llm="gpt-4o-mini" | ||
| llm="gpt-5.4" | ||
| ) | ||
|
|
||
| # Define task and execute | ||
|
|
@@ -297,7 +304,7 @@ feedback_tool = tools.get_tool("tool_feedback") | |
| result = feedback_tool.call( | ||
| feedback="The HRIS tools are working great! Very fast response times.", | ||
| account_id="acc_123456", | ||
| tool_names=["bamboohr_list_employees", "bamboohr_get_employee"] | ||
| tool_names=["workday_list_workers", "workday_get_worker"] | ||
| ) | ||
| ``` | ||
|
|
||
|
|
@@ -313,9 +320,12 @@ Search for tools using natural language queries. Works with both semantic (cloud | |
| ### Basic Usage | ||
|
|
||
| ```python | ||
| import os | ||
|
|
||
| # Get a callable search tool | ||
| toolset = StackOneToolSet() | ||
| all_tools = toolset.fetch_tools(account_ids=["your-account-id"]) | ||
| account_id = os.getenv("STACKONE_ACCOUNT_ID") | ||
| all_tools = toolset.fetch_tools(account_ids=[account_id]) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: This example fetches account-scoped tools, but the later Prompt for AI agents |
||
| search_tool = toolset.get_search_tool() | ||
|
|
||
| # Search for relevant tools — returns a Tools collection | ||
|
|
@@ -327,15 +337,17 @@ tools[0](limit=10) | |
|
|
||
| ## Semantic Search | ||
|
|
||
| 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`. | ||
| 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`. | ||
|
|
||
| ```python | ||
| import os | ||
| from stackone_ai import StackOneToolSet | ||
|
|
||
| toolset = StackOneToolSet() | ||
|
|
||
| # Search by intent — returns Tools collection ready for any framework | ||
| tools = toolset.search_tools("manage employee records", account_ids=["your-account-id"], top_k=5) | ||
| account_id = os.getenv("STACKONE_ACCOUNT_ID") | ||
| tools = toolset.search_tools("manage employee records", account_ids=[account_id], top_k=5) | ||
| openai_tools = tools.to_openai() | ||
|
|
||
| # Lightweight: inspect results without fetching full tool definitions | ||
|
|
@@ -357,19 +369,31 @@ tools = toolset.search_tools("manage employees", search="semantic") | |
| tools = toolset.search_tools("manage employees", search="local") | ||
| ``` | ||
|
|
||
| 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. | ||
| 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. | ||
|
|
||
| ## Examples | ||
|
|
||
| For more examples, check out the [examples/](examples/) directory: | ||
|
|
||
| - [StackOne Account IDs](examples/stackone_account_ids.py) | ||
| - [File Uploads](examples/file_uploads.py) | ||
| - [OpenAI Integration](examples/openai_integration.py) | ||
| - [LangChain Integration](examples/langchain_integration.py) | ||
| - [CrewAI Integration](examples/crewai_integration.py) | ||
| - [Search Tool](examples/search_tool_example.py) | ||
| - [Semantic Search](examples/semantic_search_example.py) | ||
| - [OpenAI Integration](examples/openai_integration.py) — OpenAI function calling | ||
| - [LangChain Integration](examples/langchain_integration.py) — LangChain tools | ||
| - [CrewAI Integration](examples/crewai_integration.py) — CrewAI agent | ||
| - [Search Tools](examples/search_tools.py) — Tool discovery (semantic, local, auto search) | ||
| - [Auth Management](examples/auth_management.py) — API key and account ID patterns | ||
|
|
||
| ### Running Examples | ||
|
|
||
| ```bash | ||
| # 1. Set up credentials | ||
| cp .env.example .env | ||
| # Edit .env with your API keys | ||
|
|
||
| # 2. Install dependencies | ||
| uv sync --all-extras | ||
|
|
||
| # 3. Run any example | ||
| uv run examples/search_tools.py | ||
| ``` | ||
|
|
||
| ## Development | ||
|
|
||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As written, this snippet will pass
[None]asaccount_idswhenSTACKONE_ACCOUNT_IDis unset, which can lead to a confusing runtime error. Update the docs snippet to either (a) show a guard/early-exit whenaccount_idis missing, or (b) inline a note thatSTACKONE_ACCOUNT_IDmust be set before running the snippet.