Skip to content

refactor(cli): migrate existing langgraph/pydantic-ai templates to unified surface#429

Merged
declan-scale merged 1 commit into
nextfrom
declan-scale/templates-unified-surface
Jun 23, 2026
Merged

refactor(cli): migrate existing langgraph/pydantic-ai templates to unified surface#429
declan-scale merged 1 commit into
nextfrom
declan-scale/templates-unified-surface

Conversation

@declan-scale

@declan-scale declan-scale commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Third slice of #425. Migrates the existing agentex init templates onto the unified harness surface, matching the tutorial migration in #428.

  • default-langgraph, default-pydantic-ai, sync-langgraph, sync-pydantic-ai, temporal-pydantic-ai: scaffolded acp.py / agent.py now use the unified surface.
  • No new template dirs here (those land in the template PRs).

Test plan

  • pytest tests/lib/cli/ -k "init or template" — 19 passed (all templates render to valid Python)

Notes

Stacked on #428 (base = declan-scale/tutorials-unified-surface). Retarget to next after #428 merges.

🤖 Generated with Claude Code

Greptile Summary

This PR is the third slice of the unified harness surface migration, updating the five existing agentex init scaffolding templates (default-langgraph, default-pydantic-ai, sync-langgraph, sync-pydantic-ai, temporal-pydantic-ai) to use UnifiedEmitter + the new *Turn classes instead of the old stream_*_events helpers and LangChain callback tracing handlers.

  • LangGraphTurn and PydanticAITurn are promoted to the public agentex.lib.adk facade (__all__), ensuring generated user project files import only from the stable public API.
  • All five templates have their direct create_*_tracing_handler/stream_*_events/convert_*_to_agentex_events calls replaced by LangGraphTurn/PydanticAITurn + emitter.yield_turn or emitter.auto_send_turn, matching the pattern established in the tutorials PR (refactor(tutorials): migrate to the unified harness surface + renumber #428).

Confidence Score: 5/5

Safe to merge; all five templates correctly adopt the unified harness surface with no new functional regressions introduced.

The changes are mechanical migrations: old helpers replaced with Turn + UnifiedEmitter, public exports promoted for the two new Turn classes, and import paths cleaned up. The core delivery logic (auto_send_turn, yield_turn, SpanDeriver/SpanTracer) is unchanged and already reviewed in the harness PR. MODEL_NAME imports are valid in both pydantic-ai agent templates, and the tee_messages capture pattern in default-pydantic-ai is preserved correctly.

temporal-pydantic-ai/project/agent.py.j2 carries a pre-existing open question about per-activity SpanTracer lifecycle under TemporalAgent (flagged in a prior review round); no new issues introduced here.

Important Files Changed

Filename Overview
src/agentex/lib/adk/init.py Promotes LangGraphTurn and PydanticAITurn into the public all so user-facing templates import from the stable surface rather than private _modules subpaths.
src/agentex/lib/cli/templates/default-langgraph/project/acp.py.j2 Replaces create_langgraph_tracing_handler callback + stream_langgraph_events with LangGraphTurn(model=None) + UnifiedEmitter.auto_send_turn; turn_span.output updated to use result.final_text.
src/agentex/lib/cli/templates/default-pydantic-ai/project/acp.py.j2 Replaces create_pydantic_ai_tracing_handler + stream_pydantic_ai_events with PydanticAITurn(model=MODEL_NAME) + UnifiedEmitter.auto_send_turn; tee_messages pattern preserved for capturing message history; MODEL_NAME correctly imported from project.agent.
src/agentex/lib/cli/templates/sync-langgraph/project/acp.py.j2 Replaces create_langgraph_tracing_handler + convert_langgraph_to_agentex_events with LangGraphTurn(model=None) + emitter.yield_turn; final_text accumulation logic unchanged.
src/agentex/lib/cli/templates/sync-pydantic-ai/project/acp.py.j2 Replaces create_pydantic_ai_tracing_handler + convert_pydantic_ai_to_agentex_events with PydanticAITurn(model=MODEL_NAME) + emitter.yield_turn inside existing run_stream_events context manager.
src/agentex/lib/cli/templates/temporal-pydantic-ai/project/agent.py.j2 Replaces create_pydantic_ai_tracing_handler + stream_pydantic_ai_events in event_handler with PydanticAITurn + UnifiedEmitter.auto_send_turn; a fresh SpanTracer is constructed per event_handler invocation (in-memory span state not shared across Temporal activity calls).

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant ACP as acp.py (template)
    participant UE as UnifiedEmitter
    participant Turn as LangGraphTurn / PydanticAITurn
    participant SD as SpanDeriver
    participant ST as SpanTracer
    participant Str as adk.streaming (Redis)

    Note over ACP,Str: async (default-*) templates — auto_send_turn path
    ACP->>UE: UnifiedEmitter(task_id, trace_id, parent_span_id)
    UE->>ST: SpanTracer(trace_id, parent_span_id)
    ACP->>Turn: "LangGraphTurn(stream, model=None) / PydanticAITurn(stream, model=MODEL_NAME)"
    ACP->>UE: auto_send_turn(turn)
    UE->>SD: SpanDeriver()
    loop for each StreamTaskMessage event
        Turn-->>UE: event
        UE->>SD: observe(event)
        SD-->>UE: SpanSignals (OpenSpan / CloseSpan)
        UE->>ST: handle(signal) → start_span / end_span
        UE->>Str: streaming_task_message_context / stream_update
    end
    UE->>SD: flush() → close unclosed spans
    UE-->>ACP: TurnResult(final_text, usage)

    Note over ACP,Str: sync (sync-*) templates — yield_turn path
    ACP->>UE: UnifiedEmitter(task_id, trace_id, parent_span_id)
    ACP->>Turn: LangGraphTurn / PydanticAITurn
    ACP->>UE: yield_turn(turn)
    loop for each event
        Turn-->>UE: event
        UE->>SD: observe(event) → SpanSignals
        UE->>ST: handle(signal)
        UE-->>ACP: yield event
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant ACP as acp.py (template)
    participant UE as UnifiedEmitter
    participant Turn as LangGraphTurn / PydanticAITurn
    participant SD as SpanDeriver
    participant ST as SpanTracer
    participant Str as adk.streaming (Redis)

    Note over ACP,Str: async (default-*) templates — auto_send_turn path
    ACP->>UE: UnifiedEmitter(task_id, trace_id, parent_span_id)
    UE->>ST: SpanTracer(trace_id, parent_span_id)
    ACP->>Turn: "LangGraphTurn(stream, model=None) / PydanticAITurn(stream, model=MODEL_NAME)"
    ACP->>UE: auto_send_turn(turn)
    UE->>SD: SpanDeriver()
    loop for each StreamTaskMessage event
        Turn-->>UE: event
        UE->>SD: observe(event)
        SD-->>UE: SpanSignals (OpenSpan / CloseSpan)
        UE->>ST: handle(signal) → start_span / end_span
        UE->>Str: streaming_task_message_context / stream_update
    end
    UE->>SD: flush() → close unclosed spans
    UE-->>ACP: TurnResult(final_text, usage)

    Note over ACP,Str: sync (sync-*) templates — yield_turn path
    ACP->>UE: UnifiedEmitter(task_id, trace_id, parent_span_id)
    ACP->>Turn: LangGraphTurn / PydanticAITurn
    ACP->>UE: yield_turn(turn)
    loop for each event
        Turn-->>UE: event
        UE->>SD: observe(event) → SpanSignals
        UE->>ST: handle(signal)
        UE-->>ACP: yield event
    end
Loading

Reviews (6): Last reviewed commit: "refactor(cli): migrate existing langgrap..." | Re-trigger Greptile

@declan-scale declan-scale force-pushed the declan-scale/tutorials-unified-surface branch from f35bef7 to b3efb55 Compare June 23, 2026 13:54
@declan-scale declan-scale force-pushed the declan-scale/templates-unified-surface branch from 50a0533 to a6a4a30 Compare June 23, 2026 13:54
Comment thread src/agentex/lib/cli/templates/default-langgraph/project/acp.py.j2 Outdated
Comment thread src/agentex/lib/cli/templates/default-pydantic-ai/project/acp.py.j2 Outdated
@declan-scale declan-scale force-pushed the declan-scale/tutorials-unified-surface branch from b3efb55 to 1e6b84c Compare June 23, 2026 15:22
@declan-scale declan-scale force-pushed the declan-scale/templates-unified-surface branch from a6a4a30 to fb4111f Compare June 23, 2026 15:23
@declan-scale declan-scale changed the title refactor(cli)!: migrate existing langgraph/pydantic-ai templates to unified surface refactor(cli): migrate existing langgraph/pydantic-ai templates to unified surface Jun 23, 2026
@declan-scale

Copy link
Copy Markdown
Contributor Author

@greptile review

@declan-scale

Copy link
Copy Markdown
Contributor Author

@greptile review

@declan-scale declan-scale force-pushed the declan-scale/tutorials-unified-surface branch from 1e6b84c to 5f23b89 Compare June 23, 2026 19:53
@declan-scale declan-scale force-pushed the declan-scale/templates-unified-surface branch from fb4111f to c9f7ab7 Compare June 23, 2026 19:53
@declan-scale declan-scale force-pushed the declan-scale/tutorials-unified-surface branch from 5f23b89 to f06e819 Compare June 23, 2026 19:56
@declan-scale declan-scale force-pushed the declan-scale/templates-unified-surface branch from c9f7ab7 to 8debccd Compare June 23, 2026 19:56
@declan-scale declan-scale force-pushed the declan-scale/tutorials-unified-surface branch from f06e819 to 9b36537 Compare June 23, 2026 20:13
Base automatically changed from declan-scale/tutorials-unified-surface to next June 23, 2026 20:52
…ified surface

Update the scaffolded acp.py / agent.py for default-langgraph,
default-pydantic-ai, sync-langgraph, sync-pydantic-ai and temporal-pydantic-ai
to the canonical unified harness surface, matching the migrated tutorials.

Promote LangGraphTurn and PydanticAITurn to the public agentex.lib.adk facade
(parallel to ClaudeCodeTurn / CodexTurn) so the scaffolded user code imports
them from the stable public path instead of a private _modules path.

Non-breaking: template scaffolding + additive public exports only. The unified
surface already exists; deprecated tracing handlers are removed in follow-ups.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@declan-scale declan-scale force-pushed the declan-scale/templates-unified-surface branch from 8debccd to 758d5f8 Compare June 23, 2026 20:53
@declan-scale declan-scale merged commit ee41408 into next Jun 23, 2026
48 checks passed
@declan-scale declan-scale deleted the declan-scale/templates-unified-surface branch June 23, 2026 21:05
@stainless-app stainless-app Bot mentioned this pull request Jun 23, 2026
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.

2 participants