Feat/mcp structured tool results - #135
Conversation
Add an immutable, versioned tool-result contract and make execution claims safe for concurrent replay. Preserve legacy text records while preventing terminal ledger overwrites.
Normalize MCP and local tool outputs once at the provider boundary, expose structured values to trusted hooks, and keep model messages and logs text-only. Cover structured-only, malformed, replay, concurrency, and HITL behavior.
Document normalization ownership, model visibility, artifact bounds, hook compatibility, and concurrency-safe persisted replay in ADR 0004 and runtime guides.
AmitAvital1
left a comment
There was a problem hiding this comment.
Requesting changes for correctness and contract issues found in the structured-result execution path; details are inline.
Make terminal execution writes cancellation-safe, model execution states with a StrEnum, bound structured JSON payloads, and require the MCP adapter version that provides the structured-content artifact contract. Add regressions for cancellation with duplicate waiters and oversized MCP structured results.
Record the structured JSON budgets, execution status enum, cancellation-safe ledger expectations, and langchain-mcp-adapters 0.2 minimum.
|
Thanks for the detailed review — I addressed all four findings:
|
AmitAvital1
left a comment
There was a problem hiding this comment.
Re-reviewed 91f90c3: the dependency floor, bounded JSON policy, and execution-status enum are fixed and those threads are resolved.
Cancellation safety still double-finalizes a successful execution under cancellation; see the inline reproduction, so I cannot approve this head yet.
Keep the terminal success write outside pre-publication recovery so cancellation does not attempt a second failed finalization. Add a regression covering the waiting duplicate and exactly-once provider execution.
|
Thanks for the re-review and clear reproduction. I’ve fixed the remaining cancellation race. The success path now distinguishes between:
I also added the symmetric regression test. It verifies that cancellation during a blocked successful write:
Validation is clean: Ruff, mypy, and the full suite pass with 970 tests passed. |
AmitAvital1
left a comment
There was a problem hiding this comment.
Re-reviewed 828b6de: the cancellation race now preserves the terminal success result, propagates CancelledError, and keeps provider execution exactly once.
The regression test and independent reproduction pass; all previous findings are resolved and CI is green.
Summary
Preserve structured MCP tool results throughout Extra's execution pipeline instead of collapsing every successful tool result into plain text.
This builds on #133, which fixed MCP text extraction, and adds a provider-agnostic normalized tool-result model that keeps:
The structured result now survives hooks, persistence, idempotent replay, and HITL resume without leaking provider-specific LangChain objects into the core runtime.
What changed
structuredContentinstead of dropping it.dict/listtool results where applicable.ToolMessage.transform_tool_resulthooks compatible while preserving structured data.Runtime flow
Provider / LangChain result
↓
Tool-result normalization
↓
NormalizedToolResult
├── text
├── structured
└── bounded artifact metadata
↓
Hooks
↓
Execution ledger
↓
Replay / HITL resume
text only
↓
Model conversation
Backwards compatibility
Tests
Added/updated coverage for:
structuredContent;Validation
git diff --checkpassed.Out of scope