From ad5c805e17c51abd92773751416748b7fbc51de7 Mon Sep 17 00:00:00 2001 From: francisco-orkes Date: Fri, 14 Aug 2026 14:41:48 -0700 Subject: [PATCH 1/6] Fix six issues found running the agent examples - settings.py docstring claimed the default model was anthropic/claude-sonnet-4-6; the code defaults to openai/gpt-4o (#485). - Add langchain-anthropic to the langchain and agents extras, so langgraph/43_react_agent_multi_model.py runs after the documented install. It requires anthropic >=0.120 and langchain-core >=1.5.4, which the lock file now reflects (#486). - Wrap the body of langgraph/46_crash_and_resume.py in a __main__ guard. Without it, spawned workers re-imported the module and re-ran the whole demo. The tools and graph stay at module level so workers can still rebuild them (#489). - Replace anthropic/claude-sonnet-4-20250514, which the API answers with 404 not_found_error, with anthropic/claude-sonnet-5, the replacement #494 verified against a live server (#480). - 74_cli_error_output.py asserted against result.output, which is a dict, so the substring check tested keys and the example could never pass. Use str(result.output), as the other examples that need a string do (#481). - Point run_examples.sh at examples/agents. It globbed examples/, where no numbered examples live, so it collected nothing and always passed (#484). Because that glob matched nothing, the script's skip list had never been exercised. Add the examples that must not run unattended: seven that act on real third-party accounts, and eight that block on stdin with no canned response. --all still runs them. Co-Authored-By: Claude Opus 5 (1M context) --- .../agentic_workflows/mcp_weather_agent.py | 2 +- examples/agents/56_rag_agent.py | 2 +- examples/agents/59_coding_agent.py | 4 +- examples/agents/60_github_coding_agent.py | 8 +- .../agents/60a_github_coding_agent_simple.py | 8 +- examples/agents/74_cli_error_output.py | 2 +- examples/agents/adk/35_rag_agent.py | 2 +- .../agents/langgraph/46_crash_and_resume.py | 148 +++++++++--------- examples/agents/settings.py | 4 +- poetry.lock | 64 +++++--- pyproject.toml | 8 +- scripts/run_examples.sh | 26 ++- 12 files changed, 161 insertions(+), 117 deletions(-) diff --git a/examples/agentic_workflows/mcp_weather_agent.py b/examples/agentic_workflows/mcp_weather_agent.py index 8c0b21c7d..d89586ae6 100644 --- a/examples/agentic_workflows/mcp_weather_agent.py +++ b/examples/agentic_workflows/mcp_weather_agent.py @@ -90,7 +90,7 @@ def create_mcp_agent_workflow(executor: WorkflowExecutor, mcp_server: str) -> Co plan_task = LlmChatComplete( task_ref_name="plan_action", llm_provider="anthropic", - model="claude-sonnet-4-20250514", + model="claude-sonnet-5", messages=[ ChatMessage( role="system", diff --git a/examples/agents/56_rag_agent.py b/examples/agents/56_rag_agent.py index abccf4c93..3ae8af331 100644 --- a/examples/agents/56_rag_agent.py +++ b/examples/agents/56_rag_agent.py @@ -65,7 +65,7 @@ "text": ( "Agent Configuration. Agents are defined with a name, model, instructions, " "and tools. The model field uses the format 'provider/model_name', e.g. " - "'openai/gpt-4o' or 'anthropic/claude-sonnet-4-20250514'. Instructions can be " + "'openai/gpt-4o' or 'anthropic/claude-sonnet-5'. Instructions can be " "a string or a PromptTemplate referencing a stored prompt. Tools can be " "@tool-decorated Python functions, http_tool for REST APIs, mcp_tool for " "MCP servers, or agent_tool to wrap another agent as a callable tool. " diff --git a/examples/agents/59_coding_agent.py b/examples/agents/59_coding_agent.py index cc531e5f1..7f9fe50cb 100644 --- a/examples/agents/59_coding_agent.py +++ b/examples/agents/59_coding_agent.py @@ -26,7 +26,7 @@ qa_tester = Agent( name="qa_tester", - model="anthropic/claude-sonnet-4-20250514", + model="anthropic/claude-sonnet-5", instructions=( "You are a meticulous QA engineer. Review the code written by the " "coder for correctness, edge cases, and bugs. Write and execute test " @@ -45,7 +45,7 @@ coder = Agent( name="coder", - model="anthropic/claude-sonnet-4-20250514", + model="anthropic/claude-sonnet-5", instructions=( "You are an expert Python developer. Write clean, well-structured " "Python code to solve the given problem. Always execute your code to " diff --git a/examples/agents/60_github_coding_agent.py b/examples/agents/60_github_coding_agent.py index 0ff32d2a9..ae5f64726 100644 --- a/examples/agents/60_github_coding_agent.py +++ b/examples/agents/60_github_coding_agent.py @@ -249,7 +249,7 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: github_agent = Agent( name="github_agent", - model="anthropic/claude-sonnet-4-20250514", + model="anthropic/claude-sonnet-5", instructions=( "You are a GitHub operations specialist. You handle all git and " "GitHub CLI interactions.\n\n" @@ -282,7 +282,7 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: coder = Agent( name="coder", - model="anthropic/claude-sonnet-4-20250514", + model="anthropic/claude-sonnet-5", instructions=( "You are an expert developer. Write clean, well-structured code.\n\n" "WHEN YOU RECEIVE A TASK:\n" @@ -311,7 +311,7 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: qa_tester = Agent( name="qa_tester", - model="anthropic/claude-sonnet-4-20250514", + model="anthropic/claude-sonnet-5", instructions=( "You are a meticulous QA engineer. Review the code written by the " "coder for correctness, edge cases, and bugs.\n\n" @@ -340,7 +340,7 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: coding_team = Agent( name="coding_team", - model="anthropic/claude-sonnet-4-20250514", + model="anthropic/claude-sonnet-5", instructions=( "You are a coding team coordinator. Delegate the incoming request " "to github_agent to get started — it will pick an issue and set " diff --git a/examples/agents/60a_github_coding_agent_simple.py b/examples/agents/60a_github_coding_agent_simple.py index 7454e0125..3842efc70 100644 --- a/examples/agents/60a_github_coding_agent_simple.py +++ b/examples/agents/60a_github_coding_agent_simple.py @@ -41,7 +41,7 @@ github_agent = Agent( name="github_agent", - model="anthropic/claude-sonnet-4-20250514", + model="anthropic/claude-sonnet-5", instructions=( "You are a GitHub operations specialist. You handle all git and " "GitHub CLI interactions.\n\n" @@ -77,7 +77,7 @@ coder = Agent( name="coder", - model="anthropic/claude-sonnet-4-20250514", + model="anthropic/claude-sonnet-5", instructions=( "You are an expert developer. You write clean, well-structured code.\n\n" f"The repo is cloned at {WORK_DIR}.\n\n" @@ -109,7 +109,7 @@ qa_tester = Agent( name="qa_tester", - model="anthropic/claude-sonnet-4-20250514", + model="anthropic/claude-sonnet-5", instructions=( "You are a meticulous QA engineer. Review the code written by the " "coder for correctness, edge cases, and bugs.\n\n" @@ -134,7 +134,7 @@ coding_team = Agent( name="coding_team", - model="anthropic/claude-sonnet-4-20250514", + model="anthropic/claude-sonnet-5", instructions=( "You are a coding team coordinator. Delegate the incoming request " "to github_agent to get started — it will pick an issue and set " diff --git a/examples/agents/74_cli_error_output.py b/examples/agents/74_cli_error_output.py index 4f0a586db..87b82f502 100644 --- a/examples/agents/74_cli_error_output.py +++ b/examples/agents/74_cli_error_output.py @@ -36,7 +36,7 @@ with AgentRuntime() as rt: result = rt.run(agent, prompt) result.print_result() - output = result.output or "" + output = str(result.output) # Verify the agent saw the error output assert "No such file or directory" in output or "nonexistent" in output, ( diff --git a/examples/agents/adk/35_rag_agent.py b/examples/agents/adk/35_rag_agent.py index 250224bf1..c9060a8fd 100644 --- a/examples/agents/adk/35_rag_agent.py +++ b/examples/agents/adk/35_rag_agent.py @@ -76,7 +76,7 @@ "text": ( "Agent Configuration. Agents are defined with a name, model, instructions, " "and tools. The model field uses the format 'provider/model_name', e.g. " - "'openai/gpt-4o' or 'anthropic/claude-sonnet-4-20250514'. Instructions can be " + "'openai/gpt-4o' or 'anthropic/claude-sonnet-5'. Instructions can be " "a string or a PromptTemplate referencing a stored prompt. Tools can be " "@tool-decorated Python functions, http_tool for REST APIs, mcp_tool for " "MCP servers, or agent_tool to wrap another agent as a callable tool. " diff --git a/examples/agents/langgraph/46_crash_and_resume.py b/examples/agents/langgraph/46_crash_and_resume.py index adc112e50..df27a41c9 100644 --- a/examples/agents/langgraph/46_crash_and_resume.py +++ b/examples/agents/langgraph/46_crash_and_resume.py @@ -104,80 +104,80 @@ def generate_report(analysis: str) -> str: ) -# -- Phase 1: Deploy, start, serve briefly, then crash -------------------- - -print("=" * 60) -print("Phase 1: Deploy + start, then simulate crash") -print("=" * 60) - -with AgentRuntime() as runtime: - # Deploy the workflow definition (in production, do this once in CI/CD) - runtime.deploy(graph) - print("Agent deployed to server.") - - # Start an execution by name — the agent is already deployed on the server, - # so we only need to send the name and prompt (not the full graph object). - handle = runtime.start( - "sales_analyst", - "Fetch the Q4 2025 sales data, run a full trend analysis on it, " - "then generate an executive summary report. " - "Call each tool in sequence — do not skip any step.", - ) - print(f"Execution started: {handle.execution_id}") - - # Save execution_id so we can check status later - with open(SESSION_FILE, "w") as f: - f.write(handle.execution_id) - - # Serve workers just long enough for the first tool to start - print("\nServing workers briefly...") - runtime.serve(graph, blocking=False) - time.sleep(8) - -print("\nRuntime closed — workers are dead, workflow persists on server.") -print() - -with open(SESSION_FILE) as f: - saved_execution_id = f.read().strip() - -# -- Pause: let the user see the stalled execution in the UI -------------- - -ui_link = f"{UI_BASE}/execution/{saved_execution_id}" -print("-" * 60) -print("Open the Conductor UI to see the execution in RUNNING state:") -print(f" {ui_link}") -print() -print("The workflow is alive on the server but stalled — no workers are") -print("polling to pick up the next task. The completed steps are") -print("preserved; only the remaining steps need to run.") -print("-" * 60) -input("\nPress Enter to resume (restart workers)...") -print() - - -# -- Phase 2: Restart serve — workers pick up stalled tasks ---------------- - -print("=" * 60) -print("Phase 2: Restart serve() — workers reconnect automatically") -print("=" * 60) - -with AgentRuntime() as runtime: - # serve() re-registers the same workers. The server dispatches - # stalled tasks to them — no resume() call needed. - print("\nServing workers (non-blocking for demo)...") - runtime.serve(graph, blocking=False) - - # Poll until the execution completes - print(f"Polling execution: {saved_execution_id}") - status = runtime.get_status(saved_execution_id) - while not status.is_complete: - time.sleep(2) +if __name__ == "__main__": + # -- Phase 1: Deploy, start, serve briefly, then crash -------------------- + + print("=" * 60) + print("Phase 1: Deploy + start, then simulate crash") + print("=" * 60) + + with AgentRuntime() as runtime: + # Deploy the workflow definition (in production, do this once in CI/CD) + runtime.deploy(graph) + print("Agent deployed to server.") + + # Start an execution by name — the agent is already deployed on the server, + # so we only need to send the name and prompt (not the full graph object). + handle = runtime.start( + "sales_analyst", + "Fetch the Q4 2025 sales data, run a full trend analysis on it, " + "then generate an executive summary report. " + "Call each tool in sequence — do not skip any step.", + ) + print(f"Execution started: {handle.execution_id}") + + # Save execution_id so we can check status later + with open(SESSION_FILE, "w") as f: + f.write(handle.execution_id) + + # Serve workers just long enough for the first tool to start + print("\nServing workers briefly...") + runtime.serve(graph, blocking=False) + time.sleep(8) + + print("\nRuntime closed — workers are dead, workflow persists on server.") + print() + + with open(SESSION_FILE) as f: + saved_execution_id = f.read().strip() + + # -- Pause: let the user see the stalled execution in the UI -------------- + + ui_link = f"{UI_BASE}/execution/{saved_execution_id}" + print("-" * 60) + print("Open the Conductor UI to see the execution in RUNNING state:") + print(f" {ui_link}") + print() + print("The workflow is alive on the server but stalled — no workers are") + print("polling to pick up the next task. The completed steps are") + print("preserved; only the remaining steps need to run.") + print("-" * 60) + input("\nPress Enter to resume (restart workers)...") + print() + + # -- Phase 2: Restart serve — workers pick up stalled tasks ---------------- + + print("=" * 60) + print("Phase 2: Restart serve() — workers reconnect automatically") + print("=" * 60) + + with AgentRuntime() as runtime: + # serve() re-registers the same workers. The server dispatches + # stalled tasks to them — no resume() call needed. + print("\nServing workers (non-blocking for demo)...") + runtime.serve(graph, blocking=False) + + # Poll until the execution completes + print(f"Polling execution: {saved_execution_id}") status = runtime.get_status(saved_execution_id) - print(f" status: {status.status}") + while not status.is_complete: + time.sleep(2) + status = runtime.get_status(saved_execution_id) + print(f" status: {status.status}") - print(f"\nStatus: {status.status}") - print(f"Output: {status.output}") - print("\nCheck the completed execution in the UI:") - print(f" {ui_link}") + print(f"\nStatus: {status.status}") + print(f"Output: {status.output}") + print("\nCheck the completed execution in the UI:") + print(f" {ui_link}") -print("\nDone — same workflow, seamless resume after simulated crash.") + print("\nDone — same workflow, seamless resume after simulated crash.") diff --git a/examples/agents/settings.py b/examples/agents/settings.py index 0037ca423..4154ec7d7 100644 --- a/examples/agents/settings.py +++ b/examples/agents/settings.py @@ -3,10 +3,10 @@ Set ``CONDUCTOR_AGENT_LLM_MODEL`` as an environment variable to override the default model used by all examples:: - export CONDUCTOR_AGENT_LLM_MODEL=anthropic/claude-sonnet-4-20250514 + export CONDUCTOR_AGENT_LLM_MODEL=anthropic/claude-sonnet-5 export CONDUCTOR_AGENT_LLM_MODEL=google_gemini/gemini-2.0-flash -If unset, defaults to ``anthropic/claude-sonnet-4-6``. +If unset, defaults to ``openai/gpt-4o``. ``CONDUCTOR_AGENT_SECONDARY_LLM_MODEL`` provides a second model for multi-model examples (e.g., cheap triage vs capable specialist). Defaults to ``openai/gpt-4o``. diff --git a/poetry.lock b/poetry.lock index 458c4dfc1..f060aae88 100644 --- a/poetry.lock +++ b/poetry.lock @@ -37,7 +37,7 @@ description = "Reusable constraint types to use with typing.Annotated" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"openai\" or extra == \"adk\" or extra == \"anthropic\"" +markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"anthropic\" or extra == \"openai\" or extra == \"adk\"" files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -45,15 +45,15 @@ files = [ [[package]] name = "anthropic" -version = "0.116.0" +version = "0.122.0" description = "The official Python library for the anthropic API" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"anthropic\" or extra == \"agents\"" +markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"anthropic\"" files = [ - {file = "anthropic-0.116.0-py3-none-any.whl", hash = "sha256:6c0a7698e8d652455da3499978279bb2588c7264d0a35be3666009a4258c8256"}, - {file = "anthropic-0.116.0.tar.gz", hash = "sha256:5fc248fbb9fe03ef686f8a774f81586bca31a043260aab88b387ea3660f4a396"}, + {file = "anthropic-0.122.0-py3-none-any.whl", hash = "sha256:45ec906452ffae6b5f7f0c53d01f50bfb7e4ce878d7ae8e4309d13171e557e67"}, + {file = "anthropic-0.122.0.tar.gz", hash = "sha256:ffec56ae96657c8d19fa575ec96f140f380c353a07ab7d61b92eb18ee6536601"}, ] [package.dependencies] @@ -63,14 +63,15 @@ docstring-parser = ">=0.15,<1" httpx = ">=0.25.0,<1" jiter = ">=0.4.0,<1" pydantic = ">=1.9.0,<3" -sniffio = "*" +sniffio = ">=1,<2" typing-extensions = ">=4.14,<5" [package.extras] -aiohttp = ["aiohttp", "httpx-aiohttp (>=0.1.9)"] -aws = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] -bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] -mcp = ["mcp (>=1.0) ; python_version >= \"3.10\""] +aiohttp = ["aiohttp (>=3,<4)", "httpx-aiohttp (>=0.1.9,<1)"] +aws = ["boto3 (>=1.28.57,<2)", "botocore (>=1.31.57,<2)"] +bedrock = ["boto3 (>=1.28.57,<2)", "botocore (>=1.31.57,<2)"] +google-cloud = ["google-auth[requests] (>=2,<3)"] +mcp = ["mcp (>=1.0,<3) ; python_version >= \"3.10\""] vertex = ["google-auth[requests] (>=2,<3)"] webhooks = ["standardwebhooks (>=1.0.1,<2)"] @@ -726,7 +727,7 @@ description = "Distro - an OS platform information API" optional = true python-versions = ">=3.6" groups = ["main"] -markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"langgraph\" or extra == \"openai\" or extra == \"openai-agents\" or extra == \"adk\" or extra == \"anthropic\"" +markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"langgraph\" or extra == \"anthropic\" or extra == \"openai\" or extra == \"openai-agents\" or extra == \"adk\"" files = [ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, @@ -739,7 +740,7 @@ description = "Parse Python docstrings in reST, Google and Numpydoc format" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"anthropic\" or extra == \"agents\"" +markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"anthropic\"" files = [ {file = "docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b"}, {file = "docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015"}, @@ -1155,7 +1156,7 @@ description = "Fast iterable JSON parser." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"openai\" or extra == \"openai-agents\" or extra == \"anthropic\"" +markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"anthropic\" or extra == \"openai\" or extra == \"openai-agents\"" files = [ {file = "jiter-0.16.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c5fc4f8def331036a7b8e981b4347ebe409981edbc8308a5ea842b8c3614fa6c"}, {file = "jiter-0.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5a71d0d2014c3275043e1170bf3d4e771493cb0dcf07be54c567155f4d8ee64b"}, @@ -1388,20 +1389,39 @@ perplexity = ["langchain-perplexity"] together = ["langchain-together"] xai = ["langchain-xai"] +[[package]] +name = "langchain-anthropic" +version = "1.5.6" +description = "Integration package connecting Claude (Anthropic) APIs and LangChain" +optional = true +python-versions = "<4.0.0,>=3.10.0" +groups = ["main"] +markers = "extra == \"langchain\" or extra == \"agents\"" +files = [ + {file = "langchain_anthropic-1.5.6-py3-none-any.whl", hash = "sha256:c358ed2ca90ef75254bb73a96b0a8a8ef0efc1deabe529ea06db6ff403001a27"}, + {file = "langchain_anthropic-1.5.6.tar.gz", hash = "sha256:648fdab25573fc9d29543c4b4af1d682b7b6e548d452bb46e67ebc586e195629"}, +] + +[package.dependencies] +anthropic = ">=0.120.0,<1.0.0" +langchain-core = ">=1.5.4,<2.0.0" +pydantic = ">=2.7.4,<3.0.0" + [[package]] name = "langchain-core" -version = "1.4.8" +version = "1.5.5" description = "Building applications with LLMs through composability" optional = true python-versions = "<4.0.0,>=3.10.0" groups = ["main"] markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"langgraph\"" files = [ - {file = "langchain_core-1.4.8-py3-none-any.whl", hash = "sha256:d84c28b05e3ba8d4271d0827aad5b592ccdaaf986e76768c23503f0a2045e8aa"}, - {file = "langchain_core-1.4.8.tar.gz", hash = "sha256:5bf1f8411077c904182ad8f975943d36adcbf579c4e017b3a118b719229ebf9a"}, + {file = "langchain_core-1.5.5-py3-none-any.whl", hash = "sha256:537037fd44ead7c1ffb9621011029ad2e347e051519d17f112d7bf7be12f4365"}, + {file = "langchain_core-1.5.5.tar.gz", hash = "sha256:c08d78176113867e9a76acc1007d641cd68fa5682e9e0018980d062b4ae0777e"}, ] [package.dependencies] +httpx = ">=0.23.0,<1.0.0" jsonpatch = ">=1.33.0,<2.0.0" langchain-protocol = ">=0.0.17" langsmith = ">=0.3.45,<1.0.0" @@ -2237,7 +2257,7 @@ description = "Data validation using Python type hints" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"openai\" or extra == \"adk\" or extra == \"anthropic\"" +markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"anthropic\" or extra == \"openai\" or extra == \"adk\"" files = [ {file = "pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba"}, {file = "pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6"}, @@ -2260,7 +2280,7 @@ description = "Core functionality for Pydantic validation and serialization" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"openai\" or extra == \"adk\" or extra == \"anthropic\"" +markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"anthropic\" or extra == \"openai\" or extra == \"adk\"" files = [ {file = "pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4"}, {file = "pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5"}, @@ -3490,7 +3510,7 @@ description = "Runtime typing introspection tools" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"openai\" or extra == \"adk\" or extra == \"anthropic\"" +markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"anthropic\" or extra == \"openai\" or extra == \"adk\"" files = [ {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, @@ -4220,10 +4240,10 @@ cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and pyt [extras] adk = ["google-adk"] -agents = ["anthropic", "claude-code-sdk", "google-adk", "langchain", "langchain-core", "langchain-openai", "langgraph", "openai", "openai-agents"] +agents = ["anthropic", "claude-code-sdk", "google-adk", "langchain", "langchain-anthropic", "langchain-core", "langchain-openai", "langgraph", "openai", "openai-agents"] anthropic = ["anthropic"] claude = ["claude-code-sdk"] -langchain = ["langchain", "langchain-core", "langchain-openai"] +langchain = ["langchain", "langchain-anthropic", "langchain-core", "langchain-openai"] langgraph = ["langchain-core", "langgraph"] openai = ["openai"] openai-agents = ["openai-agents"] @@ -4231,4 +4251,4 @@ openai-agents = ["openai-agents"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0" -content-hash = "c9fd605d1f56bc517db3abd078ea0a56e411d01371115ba6ef4229d508b9f939" +content-hash = "e94e8ff50d9b09bfcb2cfe853dfb6f04514d3c45f92f89d3a1cb2c0e798235a7" diff --git a/pyproject.toml b/pyproject.toml index 3c2d22329..fccf9ed86 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,6 +43,7 @@ cloudpickle = ">=2.0" # Floors raised to the versions ConductorAgent's own uv.lock proved mutually compatible # (langchain's 0.3.x-floor collided with today's published 1.x line during resolution). langchain = { version = ">=1.2.13", optional = true } +langchain-anthropic = { version = ">=1.5.5", optional = true } langchain-core = { version = ">=1.2.20", optional = true } langchain-openai = { version = ">=1.1.11", optional = true } langgraph = { version = ">=1.1.3", optional = true } @@ -53,15 +54,16 @@ anthropic = { version = ">=0.91.0", optional = true } claude-code-sdk = { version = ">=0.0.25", optional = true } [tool.poetry.extras] -langchain = ["langchain", "langchain-core", "langchain-openai"] +langchain = ["langchain", "langchain-anthropic", "langchain-core", "langchain-openai"] langgraph = ["langgraph", "langchain-core"] adk = ["google-adk"] openai = ["openai"] openai-agents = ["openai-agents"] anthropic = ["anthropic"] claude = ["claude-code-sdk"] -agents = ["langchain", "langchain-core", "langchain-openai", "langgraph", - "google-adk", "openai", "openai-agents", "anthropic", "claude-code-sdk"] +agents = ["langchain", "langchain-anthropic", "langchain-core", "langchain-openai", + "langgraph", "google-adk", "openai", "openai-agents", "anthropic", + "claude-code-sdk"] [tool.poetry.group.dev.dependencies] pylint = ">=2.17.5" diff --git a/scripts/run_examples.sh b/scripts/run_examples.sh index 3a50b6d4f..cc9d7496e 100755 --- a/scripts/run_examples.sh +++ b/scripts/run_examples.sh @@ -15,7 +15,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -EXAMPLES_DIR="$(cd "$SCRIPT_DIR/../examples" && pwd)" +EXAMPLES_DIR="$(cd "$SCRIPT_DIR/../examples/agents" && pwd)" TIMEOUT="${EXAMPLE_TIMEOUT:-300}" # Cross-platform python: honour PYTHON env var, then try python3, then python. @@ -25,7 +25,8 @@ PYTHON="${PYTHON:-$(command -v python3 2>/dev/null || command -v python 2>/dev/n TMP_BASE="${TMPDIR:-${TEMP:-/tmp}}" # Examples that require external services not typically available in a -# standard test environment. +# standard test environment. Run them with --all once the services and +# credentials they need are in place. SKIP_BY_DEFAULT=( "04_http_and_mcp_tools" # needs MCP server running "04_mcp_weather" # needs MCP server running @@ -33,6 +34,27 @@ SKIP_BY_DEFAULT=( "25_semantic_memory" # needs vector store / extra deps "26_opentelemetry_tracing" # needs OTel collector "28_gpt_assistant_agent" # needs OpenAI Assistants API key + + # Act on real third-party accounts: these clone, branch, push, open pull + # requests or post messages, so a default run must not reach them. + "16c_credentials_cli_tools" # needs AWS credentials; can open PRs + "16d_credentials_gh_cli" # needs an authenticated gh CLI + "60_github_coding_agent" # pushes branches, opens PRs + "60a_github_coding_agent_simple" # clones and pushes to a real repo + "61_github_coding_agent_chained" # needs GITHUB_TOKEN; pushes branches + "61a_github_coding_agent_claude_code" # needs GITHUB_TOKEN; pushes branches + "91_slack_autofix_agent" # pushes, opens PRs, posts to Slack + + # Block on stdin with no canned response in HITL_STDIN below, so they would + # sit until the per-example timeout. + "09d_human_tool" + "18_manual_selection" + "32_human_guardrail" + "62_coding_agent_openai" + "78_approval_workflow" + "81_chat_repl" + "82_coding_agent" + "82b_coding_agent_tui" ) # HITL examples that call input() — we pipe automated responses via stdin. From c014c56cd6ade0004be587094ce1fbc6696f1bc3 Mon Sep 17 00:00:00 2001 From: francisco-orkes Date: Fri, 14 Aug 2026 17:08:34 -0700 Subject: [PATCH 2/6] Drop thinking_budget_tokens from examples 59, 60 and 60a Replacing the retired model id in the previous commit left these three failing on a different error: 400 "thinking.type.enabled" is not supported for this model. Use "thinking.type.adaptive" and "output_config.effort" to control thinking behavior. All three set thinking_budget_tokens, which the SDK serializes as {"enabled": true, "budgetTokens": N} in config_serializer.py:218 and run_settings.py:52. No Claude 4.7+ model accepts that shape, and the SDK exposes no way to emit the adaptive form the API asks for, so the parameter cannot be kept on a current model. Remove it from the eight agents that set it, and drop the docstring line in 59 that advertised the feature. 59_coding_agent.py then completes against Conductor OSS 3.32.0 in 302s. 60 and 60a are the same deletion but were not run: both act on a real GitHub repository. thinking_budget_tokens is still exercised by 50_thinking_config.py and kitchen_sink.py, which take their model from settings.llm_model. Completes #480. The SDK limitation is filed separately. Co-Authored-By: Claude Opus 5 (1M context) --- examples/agents/59_coding_agent.py | 3 --- examples/agents/60_github_coding_agent.py | 3 --- examples/agents/60a_github_coding_agent_simple.py | 3 --- 3 files changed, 9 deletions(-) diff --git a/examples/agents/59_coding_agent.py b/examples/agents/59_coding_agent.py index 7f9fe50cb..37d4686b0 100644 --- a/examples/agents/59_coding_agent.py +++ b/examples/agents/59_coding_agent.py @@ -5,7 +5,6 @@ - Coder writes code, transfers to QA when ready - QA tester reviews and runs tests, transfers back if bugs found - Natural back-and-forth until QA approves the code - - Extended thinking for step-by-step reasoning Flow (swarm — LLM-driven handoffs): 1. coder writes the solution, executes it, transfers to qa_tester @@ -37,7 +36,6 @@ "provide your final QA report. Do NOT transfer back if all tests pass." ), local_code_execution=True, - thinking_budget_tokens=4096, max_tokens=16384, ) @@ -56,7 +54,6 @@ "to qa_tester for verification." ), local_code_execution=True, - thinking_budget_tokens=4096, max_tokens=16384, # Swarm: coder starts, can hand off to qa_tester and back agents=[qa_tester], diff --git a/examples/agents/60_github_coding_agent.py b/examples/agents/60_github_coding_agent.py index ae5f64726..71d584f7c 100644 --- a/examples/agents/60_github_coding_agent.py +++ b/examples/agents/60_github_coding_agent.py @@ -274,7 +274,6 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: "transfer tool after this — the workflow ends automatically." ), tools=github_tools, - thinking_budget_tokens=4096, max_tokens=16384, ) @@ -303,7 +302,6 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: ), tools=coding_tools, local_code_execution=True, - thinking_budget_tokens=4096, max_tokens=16384, ) @@ -332,7 +330,6 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: ), tools=qa_tools, local_code_execution=True, - thinking_budget_tokens=4096, max_tokens=16384, ) diff --git a/examples/agents/60a_github_coding_agent_simple.py b/examples/agents/60a_github_coding_agent_simple.py index 3842efc70..ab7ce8cbd 100644 --- a/examples/agents/60a_github_coding_agent_simple.py +++ b/examples/agents/60a_github_coding_agent_simple.py @@ -69,7 +69,6 @@ "transfer tool — the workflow ends automatically." ), local_code_execution=True, - thinking_budget_tokens=4096, max_tokens=16384, ) @@ -101,7 +100,6 @@ "every code block runs in an isolated environment." ), local_code_execution=True, - thinking_budget_tokens=4096, max_tokens=16384, ) @@ -126,7 +124,6 @@ " NEVER call transfer_to_coding_team (it will be rejected)\n" ), local_code_execution=True, - thinking_budget_tokens=4096, max_tokens=16384, ) From 42c240167a7e4b326681a86c341c1ede764d20c2 Mon Sep 17 00:00:00 2001 From: francisco-orkes Date: Fri, 14 Aug 2026 17:08:43 -0700 Subject: [PATCH 3/6] Revert the packaging change; #486 moves to its own PR Restores pyproject.toml and poetry.lock to their state on main, per review feedback that they should not change on this PR. The fix itself still stands: the .[agents] and .[langchain] extras omit langchain-anthropic, so langgraph/43_react_agent_multi_model.py cannot run after the documented install. That lands separately as #486; this PR no longer carries it. Co-Authored-By: Claude Opus 5 (1M context) --- poetry.lock | 64 +++++++++++++++++--------------------------------- pyproject.toml | 8 +++---- 2 files changed, 25 insertions(+), 47 deletions(-) diff --git a/poetry.lock b/poetry.lock index f060aae88..458c4dfc1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -37,7 +37,7 @@ description = "Reusable constraint types to use with typing.Annotated" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"anthropic\" or extra == \"openai\" or extra == \"adk\"" +markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"openai\" or extra == \"adk\" or extra == \"anthropic\"" files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -45,15 +45,15 @@ files = [ [[package]] name = "anthropic" -version = "0.122.0" +version = "0.116.0" description = "The official Python library for the anthropic API" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"anthropic\"" +markers = "extra == \"anthropic\" or extra == \"agents\"" files = [ - {file = "anthropic-0.122.0-py3-none-any.whl", hash = "sha256:45ec906452ffae6b5f7f0c53d01f50bfb7e4ce878d7ae8e4309d13171e557e67"}, - {file = "anthropic-0.122.0.tar.gz", hash = "sha256:ffec56ae96657c8d19fa575ec96f140f380c353a07ab7d61b92eb18ee6536601"}, + {file = "anthropic-0.116.0-py3-none-any.whl", hash = "sha256:6c0a7698e8d652455da3499978279bb2588c7264d0a35be3666009a4258c8256"}, + {file = "anthropic-0.116.0.tar.gz", hash = "sha256:5fc248fbb9fe03ef686f8a774f81586bca31a043260aab88b387ea3660f4a396"}, ] [package.dependencies] @@ -63,15 +63,14 @@ docstring-parser = ">=0.15,<1" httpx = ">=0.25.0,<1" jiter = ">=0.4.0,<1" pydantic = ">=1.9.0,<3" -sniffio = ">=1,<2" +sniffio = "*" typing-extensions = ">=4.14,<5" [package.extras] -aiohttp = ["aiohttp (>=3,<4)", "httpx-aiohttp (>=0.1.9,<1)"] -aws = ["boto3 (>=1.28.57,<2)", "botocore (>=1.31.57,<2)"] -bedrock = ["boto3 (>=1.28.57,<2)", "botocore (>=1.31.57,<2)"] -google-cloud = ["google-auth[requests] (>=2,<3)"] -mcp = ["mcp (>=1.0,<3) ; python_version >= \"3.10\""] +aiohttp = ["aiohttp", "httpx-aiohttp (>=0.1.9)"] +aws = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] +bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] +mcp = ["mcp (>=1.0) ; python_version >= \"3.10\""] vertex = ["google-auth[requests] (>=2,<3)"] webhooks = ["standardwebhooks (>=1.0.1,<2)"] @@ -727,7 +726,7 @@ description = "Distro - an OS platform information API" optional = true python-versions = ">=3.6" groups = ["main"] -markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"langgraph\" or extra == \"anthropic\" or extra == \"openai\" or extra == \"openai-agents\" or extra == \"adk\"" +markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"langgraph\" or extra == \"openai\" or extra == \"openai-agents\" or extra == \"adk\" or extra == \"anthropic\"" files = [ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, @@ -740,7 +739,7 @@ description = "Parse Python docstrings in reST, Google and Numpydoc format" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"anthropic\"" +markers = "extra == \"anthropic\" or extra == \"agents\"" files = [ {file = "docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b"}, {file = "docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015"}, @@ -1156,7 +1155,7 @@ description = "Fast iterable JSON parser." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"anthropic\" or extra == \"openai\" or extra == \"openai-agents\"" +markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"openai\" or extra == \"openai-agents\" or extra == \"anthropic\"" files = [ {file = "jiter-0.16.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c5fc4f8def331036a7b8e981b4347ebe409981edbc8308a5ea842b8c3614fa6c"}, {file = "jiter-0.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5a71d0d2014c3275043e1170bf3d4e771493cb0dcf07be54c567155f4d8ee64b"}, @@ -1389,39 +1388,20 @@ perplexity = ["langchain-perplexity"] together = ["langchain-together"] xai = ["langchain-xai"] -[[package]] -name = "langchain-anthropic" -version = "1.5.6" -description = "Integration package connecting Claude (Anthropic) APIs and LangChain" -optional = true -python-versions = "<4.0.0,>=3.10.0" -groups = ["main"] -markers = "extra == \"langchain\" or extra == \"agents\"" -files = [ - {file = "langchain_anthropic-1.5.6-py3-none-any.whl", hash = "sha256:c358ed2ca90ef75254bb73a96b0a8a8ef0efc1deabe529ea06db6ff403001a27"}, - {file = "langchain_anthropic-1.5.6.tar.gz", hash = "sha256:648fdab25573fc9d29543c4b4af1d682b7b6e548d452bb46e67ebc586e195629"}, -] - -[package.dependencies] -anthropic = ">=0.120.0,<1.0.0" -langchain-core = ">=1.5.4,<2.0.0" -pydantic = ">=2.7.4,<3.0.0" - [[package]] name = "langchain-core" -version = "1.5.5" +version = "1.4.8" description = "Building applications with LLMs through composability" optional = true python-versions = "<4.0.0,>=3.10.0" groups = ["main"] markers = "extra == \"langchain\" or extra == \"agents\" or extra == \"langgraph\"" files = [ - {file = "langchain_core-1.5.5-py3-none-any.whl", hash = "sha256:537037fd44ead7c1ffb9621011029ad2e347e051519d17f112d7bf7be12f4365"}, - {file = "langchain_core-1.5.5.tar.gz", hash = "sha256:c08d78176113867e9a76acc1007d641cd68fa5682e9e0018980d062b4ae0777e"}, + {file = "langchain_core-1.4.8-py3-none-any.whl", hash = "sha256:d84c28b05e3ba8d4271d0827aad5b592ccdaaf986e76768c23503f0a2045e8aa"}, + {file = "langchain_core-1.4.8.tar.gz", hash = "sha256:5bf1f8411077c904182ad8f975943d36adcbf579c4e017b3a118b719229ebf9a"}, ] [package.dependencies] -httpx = ">=0.23.0,<1.0.0" jsonpatch = ">=1.33.0,<2.0.0" langchain-protocol = ">=0.0.17" langsmith = ">=0.3.45,<1.0.0" @@ -2257,7 +2237,7 @@ description = "Data validation using Python type hints" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"anthropic\" or extra == \"openai\" or extra == \"adk\"" +markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"openai\" or extra == \"adk\" or extra == \"anthropic\"" files = [ {file = "pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba"}, {file = "pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6"}, @@ -2280,7 +2260,7 @@ description = "Core functionality for Pydantic validation and serialization" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"anthropic\" or extra == \"openai\" or extra == \"adk\"" +markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"openai\" or extra == \"adk\" or extra == \"anthropic\"" files = [ {file = "pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4"}, {file = "pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5"}, @@ -3510,7 +3490,7 @@ description = "Runtime typing introspection tools" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"anthropic\" or extra == \"openai\" or extra == \"adk\"" +markers = "extra == \"openai-agents\" or extra == \"agents\" or extra == \"claude\" or extra == \"langchain\" or extra == \"langgraph\" or extra == \"openai\" or extra == \"adk\" or extra == \"anthropic\"" files = [ {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, @@ -4240,10 +4220,10 @@ cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and pyt [extras] adk = ["google-adk"] -agents = ["anthropic", "claude-code-sdk", "google-adk", "langchain", "langchain-anthropic", "langchain-core", "langchain-openai", "langgraph", "openai", "openai-agents"] +agents = ["anthropic", "claude-code-sdk", "google-adk", "langchain", "langchain-core", "langchain-openai", "langgraph", "openai", "openai-agents"] anthropic = ["anthropic"] claude = ["claude-code-sdk"] -langchain = ["langchain", "langchain-anthropic", "langchain-core", "langchain-openai"] +langchain = ["langchain", "langchain-core", "langchain-openai"] langgraph = ["langchain-core", "langgraph"] openai = ["openai"] openai-agents = ["openai-agents"] @@ -4251,4 +4231,4 @@ openai-agents = ["openai-agents"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0" -content-hash = "e94e8ff50d9b09bfcb2cfe853dfb6f04514d3c45f92f89d3a1cb2c0e798235a7" +content-hash = "c9fd605d1f56bc517db3abd078ea0a56e411d01371115ba6ef4229d508b9f939" diff --git a/pyproject.toml b/pyproject.toml index fccf9ed86..3c2d22329 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,6 @@ cloudpickle = ">=2.0" # Floors raised to the versions ConductorAgent's own uv.lock proved mutually compatible # (langchain's 0.3.x-floor collided with today's published 1.x line during resolution). langchain = { version = ">=1.2.13", optional = true } -langchain-anthropic = { version = ">=1.5.5", optional = true } langchain-core = { version = ">=1.2.20", optional = true } langchain-openai = { version = ">=1.1.11", optional = true } langgraph = { version = ">=1.1.3", optional = true } @@ -54,16 +53,15 @@ anthropic = { version = ">=0.91.0", optional = true } claude-code-sdk = { version = ">=0.0.25", optional = true } [tool.poetry.extras] -langchain = ["langchain", "langchain-anthropic", "langchain-core", "langchain-openai"] +langchain = ["langchain", "langchain-core", "langchain-openai"] langgraph = ["langgraph", "langchain-core"] adk = ["google-adk"] openai = ["openai"] openai-agents = ["openai-agents"] anthropic = ["anthropic"] claude = ["claude-code-sdk"] -agents = ["langchain", "langchain-anthropic", "langchain-core", "langchain-openai", - "langgraph", "google-adk", "openai", "openai-agents", "anthropic", - "claude-code-sdk"] +agents = ["langchain", "langchain-core", "langchain-openai", "langgraph", + "google-adk", "openai", "openai-agents", "anthropic", "claude-code-sdk"] [tool.poetry.group.dev.dependencies] pylint = ">=2.17.5" From eabe8296906019fd3c3e812f9b413f1e43bda033 Mon Sep 17 00:00:00 2001 From: francisco-orkes Date: Fri, 14 Aug 2026 17:21:43 -0700 Subject: [PATCH 4/6] Suggest a model in settings.py that the thinking examples can use The retired id in the docstring was replaced with claude-sonnet-5, but 50_thinking_config.py and kitchen_sink.py take their model from settings.llm_model and set thinking_budget_tokens, and 70_ce_support_agent.py sets temperature. Claude 4.7+ models reject both parameters, so following the documented export broke the one example whose subject is thinking config: 400 "thinking.type.enabled" is not supported for this model. Suggest anthropic/claude-sonnet-4-6 instead, which accepts both. 50_thinking_config.py goes from failing in 16s to passing in 17s against OSS 3.32.0 and Orkes 5.5.0. The line about the default is unchanged and still fixes #485: the code defaults to openai/gpt-4o, not to the model the docstring named. Co-Authored-By: Claude Opus 5 (1M context) --- examples/agents/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/agents/settings.py b/examples/agents/settings.py index 4154ec7d7..9503fd540 100644 --- a/examples/agents/settings.py +++ b/examples/agents/settings.py @@ -3,7 +3,7 @@ Set ``CONDUCTOR_AGENT_LLM_MODEL`` as an environment variable to override the default model used by all examples:: - export CONDUCTOR_AGENT_LLM_MODEL=anthropic/claude-sonnet-5 + export CONDUCTOR_AGENT_LLM_MODEL=anthropic/claude-sonnet-4-6 export CONDUCTOR_AGENT_LLM_MODEL=google_gemini/gemini-2.0-flash If unset, defaults to ``openai/gpt-4o``. From d383fcd7fe0ddc85909c7867b4b43fda5f6b7508 Mon Sep 17 00:00:00 2001 From: francisco-orkes Date: Fri, 14 Aug 2026 17:45:39 -0700 Subject: [PATCH 5/6] Use claude-sonnet-4-6 in 59, 60 and 60a, and keep extended thinking Reverts the previous commit's removal of thinking_budget_tokens and picks a model that accepts it instead. These three set thinking_budget_tokens, which the SDK serializes as {"enabled": true, "budgetTokens": N}. Claude 4.7+ models reject that shape, and the SDK has no way to emit the adaptive form the API asks for: reasoning_effort is set on the agent config but never reaches the LLM_CHAT_COMPLETE task, so it is silently dropped rather than acting as a substitute. Dropping thinking to stay on claude-sonnet-5 therefore traded away a demonstrated feature for no gain. claude-sonnet-4-6 accepts thinking_budget_tokens and still fixes the 404 from the retired id, which is what #480 is about. It is also registered on more deployments: 59_coding_agent.py now passes against both Conductor OSS 3.32.0 (302s) and Orkes 5.5.0 (301s), where under claude-sonnet-5 the Orkes leg failed outright. The rule this leaves: examples that set thinking_budget_tokens pin claude-sonnet-4-6; everything else stays on claude-sonnet-5, matching #494. 60 and 60a were not run, as both act on a real GitHub repository. Co-Authored-By: Claude Opus 5 (1M context) --- examples/agents/59_coding_agent.py | 7 +++++-- examples/agents/60_github_coding_agent.py | 11 +++++++---- examples/agents/60a_github_coding_agent_simple.py | 11 +++++++---- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/examples/agents/59_coding_agent.py b/examples/agents/59_coding_agent.py index 37d4686b0..02d1cb244 100644 --- a/examples/agents/59_coding_agent.py +++ b/examples/agents/59_coding_agent.py @@ -5,6 +5,7 @@ - Coder writes code, transfers to QA when ready - QA tester reviews and runs tests, transfers back if bugs found - Natural back-and-forth until QA approves the code + - Extended thinking for step-by-step reasoning Flow (swarm — LLM-driven handoffs): 1. coder writes the solution, executes it, transfers to qa_tester @@ -25,7 +26,7 @@ qa_tester = Agent( name="qa_tester", - model="anthropic/claude-sonnet-5", + model="anthropic/claude-sonnet-4-6", instructions=( "You are a meticulous QA engineer. Review the code written by the " "coder for correctness, edge cases, and bugs. Write and execute test " @@ -36,6 +37,7 @@ "provide your final QA report. Do NOT transfer back if all tests pass." ), local_code_execution=True, + thinking_budget_tokens=4096, max_tokens=16384, ) @@ -43,7 +45,7 @@ coder = Agent( name="coder", - model="anthropic/claude-sonnet-5", + model="anthropic/claude-sonnet-4-6", instructions=( "You are an expert Python developer. Write clean, well-structured " "Python code to solve the given problem. Always execute your code to " @@ -54,6 +56,7 @@ "to qa_tester for verification." ), local_code_execution=True, + thinking_budget_tokens=4096, max_tokens=16384, # Swarm: coder starts, can hand off to qa_tester and back agents=[qa_tester], diff --git a/examples/agents/60_github_coding_agent.py b/examples/agents/60_github_coding_agent.py index 71d584f7c..6d2f13055 100644 --- a/examples/agents/60_github_coding_agent.py +++ b/examples/agents/60_github_coding_agent.py @@ -249,7 +249,7 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: github_agent = Agent( name="github_agent", - model="anthropic/claude-sonnet-5", + model="anthropic/claude-sonnet-4-6", instructions=( "You are a GitHub operations specialist. You handle all git and " "GitHub CLI interactions.\n\n" @@ -274,6 +274,7 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: "transfer tool after this — the workflow ends automatically." ), tools=github_tools, + thinking_budget_tokens=4096, max_tokens=16384, ) @@ -281,7 +282,7 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: coder = Agent( name="coder", - model="anthropic/claude-sonnet-5", + model="anthropic/claude-sonnet-4-6", instructions=( "You are an expert developer. Write clean, well-structured code.\n\n" "WHEN YOU RECEIVE A TASK:\n" @@ -302,6 +303,7 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: ), tools=coding_tools, local_code_execution=True, + thinking_budget_tokens=4096, max_tokens=16384, ) @@ -309,7 +311,7 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: qa_tester = Agent( name="qa_tester", - model="anthropic/claude-sonnet-5", + model="anthropic/claude-sonnet-4-6", instructions=( "You are a meticulous QA engineer. Review the code written by the " "coder for correctness, edge cases, and bugs.\n\n" @@ -330,6 +332,7 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: ), tools=qa_tools, local_code_execution=True, + thinking_budget_tokens=4096, max_tokens=16384, ) @@ -337,7 +340,7 @@ def create_pull_request(title: str, body: str, issue_number: int = 0) -> str: coding_team = Agent( name="coding_team", - model="anthropic/claude-sonnet-5", + model="anthropic/claude-sonnet-4-6", instructions=( "You are a coding team coordinator. Delegate the incoming request " "to github_agent to get started — it will pick an issue and set " diff --git a/examples/agents/60a_github_coding_agent_simple.py b/examples/agents/60a_github_coding_agent_simple.py index ab7ce8cbd..4da165853 100644 --- a/examples/agents/60a_github_coding_agent_simple.py +++ b/examples/agents/60a_github_coding_agent_simple.py @@ -41,7 +41,7 @@ github_agent = Agent( name="github_agent", - model="anthropic/claude-sonnet-5", + model="anthropic/claude-sonnet-4-6", instructions=( "You are a GitHub operations specialist. You handle all git and " "GitHub CLI interactions.\n\n" @@ -69,6 +69,7 @@ "transfer tool — the workflow ends automatically." ), local_code_execution=True, + thinking_budget_tokens=4096, max_tokens=16384, ) @@ -76,7 +77,7 @@ coder = Agent( name="coder", - model="anthropic/claude-sonnet-5", + model="anthropic/claude-sonnet-4-6", instructions=( "You are an expert developer. You write clean, well-structured code.\n\n" f"The repo is cloned at {WORK_DIR}.\n\n" @@ -100,6 +101,7 @@ "every code block runs in an isolated environment." ), local_code_execution=True, + thinking_budget_tokens=4096, max_tokens=16384, ) @@ -107,7 +109,7 @@ qa_tester = Agent( name="qa_tester", - model="anthropic/claude-sonnet-5", + model="anthropic/claude-sonnet-4-6", instructions=( "You are a meticulous QA engineer. Review the code written by the " "coder for correctness, edge cases, and bugs.\n\n" @@ -124,6 +126,7 @@ " NEVER call transfer_to_coding_team (it will be rejected)\n" ), local_code_execution=True, + thinking_budget_tokens=4096, max_tokens=16384, ) @@ -131,7 +134,7 @@ coding_team = Agent( name="coding_team", - model="anthropic/claude-sonnet-5", + model="anthropic/claude-sonnet-4-6", instructions=( "You are a coding team coordinator. Delegate the incoming request " "to github_agent to get started — it will pick an issue and set " From 85804a4fa3ab0d931f4938718b13ba0e7cfa2002 Mon Sep 17 00:00:00 2001 From: francisco-orkes Date: Fri, 14 Aug 2026 18:14:32 -0700 Subject: [PATCH 6/6] Fall back to gtimeout, or no timeout, when GNU timeout is absent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit run_examples.sh calls `timeout`, which is GNU coreutils. macOS ships neither `timeout` nor `gtimeout` unless coreutils is installed, so every example failed there with "timeout: command not found". This is not new — `timeout` is on main — but it was unreachable until the glob fix in this PR. While the script collected zero examples it always exited 0 without invoking anything, so the dependency never fired. Now that it collects 142, a default run on a Mac fails every one of them for a reason that has nothing to do with the examples. Prefer `timeout`, fall back to `gtimeout`, and run unbounded with a warning if neither exists, rather than failing everything. The banner reports which of the two applies instead of always claiming a limit. Verified both branches against Conductor OSS 3.32.0, with 74 as the example: with no timeout binary, the warning prints and 74 passes in 6s; with coreutils installed, the banner reports the 300s limit and 74 passes in 5s. The skip list is honoured either way -- `run_examples.sh 60` reports "No examples to run." rather than touching the GitHub examples. Note the script also needs bash 4+ for `declare -A`, which stock macOS bash 3.2 does not provide. That is left alone here. Co-Authored-By: Claude Opus 5 (1M context) --- scripts/run_examples.sh | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/scripts/run_examples.sh b/scripts/run_examples.sh index cc9d7496e..121e9ebcb 100755 --- a/scripts/run_examples.sh +++ b/scripts/run_examples.sh @@ -21,6 +21,15 @@ TIMEOUT="${EXAMPLE_TIMEOUT:-300}" # Cross-platform python: honour PYTHON env var, then try python3, then python. PYTHON="${PYTHON:-$(command -v python3 2>/dev/null || command -v python 2>/dev/null || echo python3)}" +# Cross-platform timeout: GNU coreutils provides `timeout`; macOS ships it as +# `gtimeout`, and only when coreutils is installed. Without either, run the +# examples unbounded rather than failing every one of them. +TIMEOUT_BIN="$(command -v timeout 2>/dev/null || command -v gtimeout 2>/dev/null || true)" +if [[ -z "$TIMEOUT_BIN" ]]; then + echo "Warning: neither 'timeout' nor 'gtimeout' found; examples will run" >&2 + echo " without a time limit. On macOS: brew install coreutils" >&2 +fi + # Cross-platform temp dir: honour TMPDIR (set on macOS/Linux), fall back to /tmp. TMP_BASE="${TMPDIR:-${TEMP:-/tmp}}" @@ -139,7 +148,11 @@ echo " Running ${#EXAMPLES[@]} examples" if [[ ${#SKIPPED[@]} -gt 0 ]]; then echo " Skipping ${#SKIPPED[@]}: ${SKIPPED[*]}" fi -echo " Timeout: ${TIMEOUT}s per example" +if [[ -n "$TIMEOUT_BIN" ]]; then + echo " Timeout: ${TIMEOUT}s per example" +else + echo " Timeout: none (no timeout binary found)" +fi echo "==========================================" echo "" @@ -163,9 +176,9 @@ for example in "${EXAMPLES[@]}"; do if [[ -n "$STDIN_RESPONSE" ]]; then # Use `yes` to provide unlimited identical responses — handles # cases where the LLM calls an approval tool multiple times. - RUN_CMD="yes '$STDIN_RESPONSE' | timeout $TIMEOUT $PYTHON $example" + RUN_CMD="yes '$STDIN_RESPONSE' | ${TIMEOUT_BIN:+$TIMEOUT_BIN $TIMEOUT }$PYTHON $example" else - RUN_CMD="timeout $TIMEOUT $PYTHON $example" + RUN_CMD="${TIMEOUT_BIN:+$TIMEOUT_BIN $TIMEOUT }$PYTHON $example" fi if eval "$RUN_CMD" > "$LOG_FILE" 2>&1; then