feat(cli): add Temporal + LangGraph agent template and example#383
Conversation
1c291ed to
3ccb61c
Compare
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
3ccb61c to
d556838
Compare
|
Pushed fixes for the failing CI + review comments (rebased on latest CI failure (the blocker): the example Review comments:
Also — made the example minimal. Per feedback that it had more state/machinery than the other LangGraph tutorials, the Re-verified locally: example tests pass (hermetic ReAct + a live end-to-end run through the real Temporal plugin on a local server), |
d556838 to
7562843
Compare
7562843 to
cf64c14
Compare
|
Thanks @smoreinis — addressed all three:
Re-verified: rendered template builds the graph, ruff clean, |
Adds a `temporal-langgraph` init template (registered in the Temporal submenu of `agentex init`) plus a runnable tutorial example, filling the gap left by the existing `temporal-openai-agents` / `temporal-pydantic-ai` templates — LangGraph previously only had `default-langgraph` and `sync-langgraph`. Uses the official Temporal LangGraph plugin (`temporalio.contrib.langgraph`, shipped in `temporalio[langgraph]>=1.27.0`): each LangGraph node runs as a durable Temporal activity (the LLM/`agent` node) or inline in the workflow (the `tools` node). Temporal is the runtime; LangGraph is the agent framework. Verified the plugin's behavior locally (Temporal dev server + real LLM) and encoded the working shape into the template: - agent node `execute_in="activity"`, tools node `execute_in="workflow"` (tool-node-as-activity is broken in the experimental plugin — AIMessage doesn't survive the activity boundary); - async router + async tools (sync callables hit run_in_executor, which Temporal's workflow loop forbids); - AgentexWorker's UnsandboxedWorkflowRunner makes langchain imports safe. Showcases nodes-as-activities, human-in-the-loop via LangGraph `interrupt` resumed by a Temporal `provide_approval` signal + `Command(resume=...)`, multi-turn memory on the workflow, graph-visualization queries (mermaid/ascii), and tracing. Example: examples/.../10_temporal/130_langgraph (full agent + tests). Tests: - tests/lib/cli/test_init_templates.py — renders every init template and asserts valid, substituted Python (catches .j2 regressions), with focused coverage of the new template (nodes-as-activities, HIL, queries, deps). - example tests/test_graph_temporal.py — hermetic graph + HIL coverage with a stub model, plus a live end-to-end run through the real Temporal plugin (skipped without LITELLM_API_KEY); tests/test_agent.py — live integration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cf64c14 to
ab18952
Compare
|
Good catch — fixed. Verified with a unit check on both shapes (OpenAI str → text; Claude block-list → joined text); ruff clean; rebased on latest |
What
Adds a
temporal-langgraphtemplate toagentex init(in the Async → Temporal submenu) and a runnable tutorial example (examples/tutorials/10_async/10_temporal/130_langgraph). LangGraph previously haddefault-langgraphandsync-langgraphbut no Temporal variant; OpenAI Agents and Pydantic AI both did.Approach: the official Temporal LangGraph plugin
Uses
temporalio.contrib.langgraph.LangGraphPlugin(shipped intemporalio[langgraph]>=1.27.0, experimental). Each LangGraph node runs as a durable Temporal activity or inline in the workflow, set per node viaexecute_in. Temporal is the runtime; LangGraph is the agent framework.Verified locally before shipping
I ran the plugin against a local Temporal server (
WorkflowEnvironment.start_local) with a real LLM and encoded the working shape into the template (the docs don't spell these out):agent(LLM) node →execute_in="activity";toolsnode →execute_in="workflow". Tool-node-as-activity is broken in the experimental plugin (theAIMessagewith tool calls doesn't survive the activity payload boundary →ToolNoderaises "No AIMessage found"); running it in the workflow keeps it intact and is also where LangGraphinterruptmust run.run_in_executor, which Temporal's workflow event loop forbids (NotImplementedError).AgentexWorker'sUnsandboxedWorkflowRunner, so langchain imports in the workflow module are fine.Showcase
interrupt; the workflow pauses on aprovide_approvalTemporal signal and resumes withCommand(resume=...).get_status,get_pending_approval,get_graph_state,get_graph_mermaid/get_graph_ascii.Tests
tests/lib/cli/test_init_templates.py— renders every init template and asserts valid, substituted Python (catches.j2regressions; already caught a Jinja brace bug), with focused coverage of the new template.tests/test_graph_temporal.py— hermetic ReAct + HIL approve/reject via a stub model (no network), plus a live end-to-end run through the real Temporal plugin (skipped unlessLITELLM_API_KEYis set).tests/test_agent.py— live integration against a running agent.Verification run in this PR
pytest tests/lib/cli/→ 59 passed.execute_inmetadata.interrupt→signal→Command(resume)) and multi-turn message round-tripping verified live on a local Temporal server.🤖 Generated with Claude Code
Greptile Summary
This PR introduces a
temporal-langgraphtemplate toagentex initand a matching runnable tutorial example, making LangGraph a first-class option alongside the existing OpenAI Agents and Pydantic AI Temporal templates. The integration usestemporalio.contrib.langgraph.LangGraphPlugin(≥ 1.27.0) to run graph nodes as durable Temporal activities, with human-in-the-loop gating via LangGraphinterruptand Temporal signals.src/agentex/lib/cli/templates/temporal-langgraph/): full project scaffold with customtools_nodesupporting HIL approval, multi-turn memory on the workflow instance, graph-visualization queries, and per-nodeexecute_inmetadata routing the LLM call to a retried activity._langgraph_messages.py): converts finished LangGraph messages to Agentex task messages afterainvoke, handling both plain-string and list-of-blocksAIMessage.content.examples/tutorials/10_async/10_temporal/130_langgraph/): simplified (no HIL) variant with hermetic ReAct tests via a stub model plus a live end-to-end Temporal-plugin test gated onLITELLM_API_KEY.Confidence Score: 4/5
Safe to merge with one open concern: the signal handler in the template workflow runs the full LangGraph turn (including awaiting LLM activities) directly inside on_task_event_send, which was flagged in a previous review thread and remains unaddressed.
The template's on_task_event_send signal handler awaits compiled.ainvoke(...) for the entire agent turn. If a second user message arrives while that await is in progress, a second handler coroutine starts concurrently, and both share self._messages, self._emitted, self._status, and self._pending_approval. Whichever handler writes last silently drops the other turn's messages. Everything else in the PR — the ADK helper, the graph template, the test suite, the pyproject deps, and the CLI wiring — looks correct and well-tested.
src/agentex/lib/cli/templates/temporal-langgraph/project/workflow.py.j2 — the on_task_event_send signal handler deserves the most attention due to the concurrent-execution concern noted in a prior review thread.
Important Files Changed
Reviews (6): Last reviewed commit: "feat(cli): add Temporal + LangGraph agen..." | Re-trigger Greptile