Skip to content

feat(examples): streamline examples, standardize auth patterns and migrate examples to Workday#179

Merged
shashi-stackone merged 7 commits intomainfrom
ENG-12642
Apr 20, 2026
Merged

feat(examples): streamline examples, standardize auth patterns and migrate examples to Workday#179
shashi-stackone merged 7 commits intomainfrom
ENG-12642

Conversation

@shashi-stackone
Copy link
Copy Markdown
Contributor

@shashi-stackone shashi-stackone commented Apr 16, 2026

Summary

  • Reduced examples from 11 to 5 focused files — removed redundant search examples, file uploads, and the old index.py quickstart
  • Standardized auth pattern: all examples read credentials from environment variables, zero hardcoded account IDs or API keys
  • Migrated all examples from BambooHR to Workday connector (most used in the ecosystem)
  • Moved benchmark utility to scripts/ directory
  • Added .env.example for easy credential setup
  • Added just run-example command and examples/README.md with setup instructions
  • Standardized OpenAI model to gpt-5.1 across all examples

Examples (before → after)

Removed: semantic_search_example.py, search_tool_example.py, agent_tool_search.py, file_uploads.py, workday_integration.py, index.py

Kept and improved:

  • openai_integration.py — OpenAI function calling
  • langchain_integration.py — LangChain tools
  • crewai_integration.py — CrewAI agent
  • search_tools.py — tool discovery (direct fetch, semantic/local/auto search, search & execute)
  • auth_management.py — API key and account ID configuration patterns

How to test

  • uv run examples/search_tools.py — all 5 sections pass with real Workday data
  • uv run examples/openai_integration.py — full OpenAI flow with real tool calls
  • uv run examples/langchain_integration.py — LangChain tool calls working
  • uv run examples/auth_management.py — all auth patterns demonstrated

Summary 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

    • Seven focused examples: openai_integration.py, langchain_integration.py, crewai_integration.py, langgraph_integration.py, pydantic_ai_integration.py, search_tools.py, auth_management.py.
    • .env.example added; examples read STACKONE_API_KEY, STACKONE_ACCOUNT_ID, OPENAI_API_KEY. just run-example helper and README “Running Examples”.
    • Workday‑first snippets and actions (workday_*) across examples and README.
    • Search‑and‑execute pattern via search_tools.py (meta tools + execution loop). Pydantic AI example now uses the public API with JSON‑schema tool conversion.
  • Refactors

    • Reduced examples from 11 → 7; removed redundant search/file‑upload/index variants and older patterns.
    • Migrated all examples from BambooHR to Workday and updated tests to match the new set.
    • Dependencies: upgraded openai, langchain-openai, langgraph; added pydantic-ai; lowered crewai to >=0.102.0.

Written for commit 933cd10. Summary will update on new commits.

Copilot AI review requested due to automatic review settings April 16, 2026 15:19
Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

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.

Comment thread examples/langchain_integration.py Outdated
Comment thread README.md
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])
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Apr 16, 2026

Choose a reason for hiding this comment

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

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>
Fix with Cubic

Comment thread examples/openai_integration.py Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.py to 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 .gitignore exception).

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.

Comment thread examples/search_tools.py Outdated
Comment on lines +134 to +148
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),
}
)
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment thread examples/openai_integration.py Outdated
Comment on lines 92 to 101
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]),
},
]
)
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment thread README.md
# 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")
Copy link

Copilot AI Apr 16, 2026

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] 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.

Suggested change
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.")

Copilot uses AI. Check for mistakes.
Comment thread examples/auth_management.py Outdated
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")
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment thread examples/crewai_integration.py Outdated
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",
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
expected_output="A JSON object containing the employee's information",
expected_output="A JSON array containing information for the first 5 employees",

Copilot uses AI. Check for mistakes.
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.

@shashi-stackone this comment seems accurate

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes that's more specific and uses correct type ..

Copy link
Copy Markdown

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

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 3 unresolved issues from previous reviews.

glebedel
glebedel previously approved these changes Apr 16, 2026
Copy link
Copy Markdown
Contributor

@glebedel glebedel left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

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

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

Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

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.

Comment thread examples/pydantic_ai_integration.py Outdated
Comment thread pyproject.toml
Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

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.

Comment thread examples/pydantic_ai_integration.py Outdated
Copy link
Copy Markdown

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

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 2 unresolved issues from previous reviews.

@shashi-stackone shashi-stackone merged commit 0bdc939 into main Apr 20, 2026
16 checks passed
@shashi-stackone shashi-stackone deleted the ENG-12642 branch April 20, 2026 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants