feat(examples): streamline examples, standardize auth patterns and migrate examples to Workday#179
feat(examples): streamline examples, standardize auth patterns and migrate examples to Workday#179shashi-stackone merged 7 commits intomainfrom
Conversation
There was a problem hiding this comment.
3 issues found across 19 files
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="examples/langchain_integration.py">
<violation number="1" location="examples/langchain_integration.py:47">
P2: Check for OPENAI_API_KEY before constructing ChatOpenAI.</violation>
</file>
<file name="README.md">
<violation number="1" location="README.md:328">
P2: This example fetches account-scoped tools, but the later `get_search_tool()` call ignores that result. Use `set_accounts()` (or pass account IDs to the search call) so the search stays scoped.</violation>
</file>
<file name="examples/openai_integration.py">
<violation number="1" location="examples/openai_integration.py:97">
P2: Handle every tool call result here instead of only the first one; otherwise multi-call model responses are truncated.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| 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.
P2: This example fetches account-scoped tools, but the later get_search_tool() call ignores that result. Use set_accounts() (or pass account IDs to the search call) so the search stays scoped.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 328:
<comment>This example fetches account-scoped tools, but the later `get_search_tool()` call ignores that result. Use `set_accounts()` (or pass account IDs to the search call) so the search stays scoped.</comment>
<file context>
@@ -313,9 +320,12 @@ Search for tools using natural language queries. Works with both semantic (cloud
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])
search_tool = toolset.get_search_tool()
</file context>
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Streamlines the Python examples by removing redundant scripts, standardizing credential/auth patterns via environment variables, and migrating the showcased HRIS connector usage from BambooHR to Workday.
Changes:
- Reduced the examples set and updated
examples/test_examples.pyto track only the retained examples. - Added new consolidated examples (
search_tools.py,auth_management.py) and updated existing OpenAI/LangChain/CrewAI examples to Workday + env-based auth. - Added developer ergonomics/docs:
just run-example,examples/README.md, and a committed.env.example(with.gitignoreexception).
Reviewed changes
Copilot reviewed 17 out of 19 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| justfile | Adds a run-example recipe to execute a single example script. |
| examples/search_tools.py | New consolidated tool discovery + search-and-execute example. |
| examples/auth_management.py | New example demonstrating API key/account ID configuration patterns. |
| examples/openai_integration.py | Migrates OpenAI example to Workday tools and env-based auth; updates model version. |
| examples/langchain_integration.py | Migrates LangChain example to Workday tools and env-based auth; updates model version. |
| examples/crewai_integration.py | Migrates CrewAI example to Workday tools and env-based auth; updates model version. |
| examples/test_examples.py | Updates the example allowlist to match the new streamlined set. |
| examples/README.md | Adds setup/run instructions and a short catalog of the remaining examples. |
| README.md | Updates docs/snippets to Workday patterns and adds example-running instructions. |
| .gitignore | Ensures .env.example is committed while ignoring real .env files. |
| .env.example | Adds a template for required env vars for running examples. |
| examples/workday_integration.py | Removes the old Workday integration example script. |
| examples/index.py | Removes the old quickstart/overview example script. |
| examples/semantic_search_example.py | Removes the legacy semantic search example. |
| examples/search_tool_example.py | Removes the legacy search tool example. |
| examples/agent_tool_search.py | Removes the legacy agent tool search example. |
| examples/file_uploads.py | Removes the legacy file upload example. |
| examples/stackone_account_ids.py | Removes the legacy account-id handling example. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| messages.append({"role": "assistant", "content": message.content, "tool_calls": message.tool_calls}) | ||
|
|
||
| for tool_call in message.tool_calls: | ||
| name = tool_call.function.name | ||
| args = json.loads(tool_call.function.arguments) | ||
| print(f" Step {step + 1}: calling {name}({json.dumps(args, indent=2)})") | ||
|
|
||
| result = toolset.execute(name, args) | ||
| messages.append( | ||
| { | ||
| "role": "tool", | ||
| "tool_call_id": tool_call.id, | ||
| "content": json.dumps(result), | ||
| } | ||
| ) |
There was a problem hiding this comment.
This agent loop is likely to break with the OpenAI client because (1) the assistant message is appended with tool_calls as SDK objects instead of the serialized dict format the API expects, and (2) toolset.execute() is called with a parsed dict (args) even though the repository’s prior usage passes the raw tool_call.function.arguments string. Prefer appending the assistant message via message.model_dump(exclude_none=True) (or equivalent) and pass the raw arguments through to toolset.execute() to match the existing SDK usage patterns.
| messages.extend( | ||
| [ | ||
| {"role": "assistant", "content": None, "tool_calls": response.choices[0].message.tool_calls}, | ||
| {"role": "assistant", "content": None, "tool_calls": tool_calls}, | ||
| { | ||
| "role": "tool", | ||
| "tool_call_id": response.choices[0].message.tool_calls[0].id, | ||
| "tool_call_id": tool_calls[0].id, | ||
| "content": str(results[0]), | ||
| }, | ||
| ] | ||
| ) |
There was a problem hiding this comment.
This continuation step only attaches the first tool result (tool_calls[0] / results[0]) even if the model returned multiple tool calls, which will desync tool_call_ids vs. tool outputs and can cause the follow-up completion to fail or hallucinate. Also, content uses str(results[0]), which produces non-JSON (e.g., single quotes) for dicts; send json.dumps(results[...]) instead, and append one tool message per tool call/result pair.
| # 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") |
There was a problem hiding this comment.
As written, this snippet will pass [None] as account_ids when STACKONE_ACCOUNT_ID is unset, which can lead to a confusing runtime error. Update the docs snippet to either (a) show a guard/early-exit when account_id is missing, or (b) inline a note that STACKONE_ACCOUNT_ID must be set before running the snippet.
| account_id = os.getenv("STACKONE_ACCOUNT_ID") | |
| account_id = os.getenv("STACKONE_ACCOUNT_ID") | |
| if not account_id: | |
| raise ValueError("Please set STACKONE_ACCOUNT_ID before running this example.") |
| print("STACKONE_API_KEY is not set. Please export it or add it to .env") | ||
| return | ||
|
|
||
| account_id = os.getenv("STACKONE_ACCOUNT_ID", "test-account-id") |
There was a problem hiding this comment.
The PR description emphasizes zero hardcoded account IDs and env-based auth; defaulting to a hardcoded test-account-id will cause the subsequent fetch_tools(...) calls to run against an invalid account by default (confusing failures) and undermines that goal. Prefer requiring STACKONE_ACCOUNT_ID (print instructions + return) or skipping the account-scoped sections when it’s not set.
| description="What is the employee with the id c28xIQaWQ6MzM5MzczMDA2NzMzMzkwNzIwNA?", | ||
| description="List the first 5 employees in the company", | ||
| agent=agent, | ||
| expected_output="A JSON object containing the employee's information", |
There was a problem hiding this comment.
expected_output doesn’t match the task description (listing 5 employees vs. a single employee’s info). Update expected_output to reflect the actual task (e.g., list/array of employees, possibly with fields), or update the task prompt to align with the expected output.
| expected_output="A JSON object containing the employee's information", | |
| expected_output="A JSON array containing information for the first 5 employees", |
There was a problem hiding this comment.
Yes that's more specific and uses correct type ..
There was a problem hiding this comment.
2 issues found across 6 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="examples/pydantic_ai_integration.py">
<violation number="1" location="examples/pydantic_ai_integration.py:22">
P2: Avoid importing `FunctionSchema` from `pydantic_ai._function_schema`; this is a private API and makes the example brittle across pydantic-ai updates.</violation>
</file>
<file name="pyproject.toml">
<violation number="1" location="pyproject.toml:41">
P2: Keep `crewai` in the `examples` extra; otherwise the CrewAI example can't be imported after `uv sync --all-extras`.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
1 issue found across 3 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="examples/pydantic_ai_integration.py">
<violation number="1" location="examples/pydantic_ai_integration.py:35">
P1: Use `Tool.from_schema` (or an explicit typed signature) here; `Tool(...)` with `**kwargs` drops the StackOne JSON schema, so the agent can't reliably call the tool.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Summary
scripts/directory.env.examplefor easy credential setupjust run-examplecommand andexamples/README.mdwith setup instructionsgpt-5.1across all examplesExamples (before → after)
Removed:
semantic_search_example.py,search_tool_example.py,agent_tool_search.py,file_uploads.py,workday_integration.py,index.pyKept and improved:
openai_integration.py— OpenAI function callinglangchain_integration.py— LangChain toolscrewai_integration.py— CrewAI agentsearch_tools.py— tool discovery (direct fetch, semantic/local/auto search, search & execute)auth_management.py— API key and account ID configuration patternsHow to test
uv run examples/search_tools.py— all 5 sections pass with real Workday datauv run examples/openai_integration.py— full OpenAI flow with real tool callsuv run examples/langchain_integration.py— LangChain tool calls workinguv run examples/auth_management.py— all auth patterns demonstratedSummary by cubic
Streamlined examples with env-based auth and a Workday‑first approach. Added LangGraph and Pydantic AI integrations and standardized OpenAI usage to
gpt-5.4, improving accuracy and ease of use across the docs (ENG‑12642).New Features
openai_integration.py,langchain_integration.py,crewai_integration.py,langgraph_integration.py,pydantic_ai_integration.py,search_tools.py,auth_management.py..env.exampleadded; examples readSTACKONE_API_KEY,STACKONE_ACCOUNT_ID,OPENAI_API_KEY.just run-examplehelper and README “Running Examples”.workday_*) across examples and README.search_tools.py(meta tools + execution loop). Pydantic AI example now uses the public API with JSON‑schema tool conversion.Refactors
openai,langchain-openai,langgraph; addedpydantic-ai; loweredcrewaito>=0.102.0.Written for commit 933cd10. Summary will update on new commits.