fix(langgraph): stop concatenating server/tool into connector_type#216
Conversation
0af0b86 to
5e641fd
Compare
MCPCheckInputRequest/MCPCheckOutputRequest now carry a genuine two-field (server, tool) identity contract (epic #2905, platform sub-issue #2904). Client.mcp_check_input/mcp_check_output gain a `tool` parameter sent as its own wire field instead of being folded into `connector_type`. mcp_tool_interceptor's default connector-type resolution now sends connector_type=request.server_name and tool=request.name as two separate values instead of the dotted "server.tool" string, and this holds even when a caller supplies a custom connector_type_fn. In tool_output_wrapper, ToolNode's call_request carries no server/origin info to improve connector_type's default beyond the bare tool name, but the tool name itself is now always forwarded via the new `tool` field rather than only living inside connector_type. Signed-off-by: Gregory Zak <gzak@getaxonflow.com>
5e641fd to
ad99e32
Compare
|
R3 review (master + independent hostile pass; platform contract verified on enterprise origin/main). Fix direction is right and the tests are strong (both-fields, custom-fn tool preservation, alias forwarding sync+async, real wire capture incl. legacy tool-omitted). Must-fix before this can join the set: BLOCKER — CI is red
MEDIUM — coordinate with #217 (guaranteed conflict)Both PRs edit the same hunks of MEDIUM — changelog gaps (cluster-wide asks)
LOW
Also note the response-plane gap filed from this review: the platform's check-output schema has no |
|
Delta note — semver classification (net-new, decision-forcing). This de-concatenation changes the wire value of Honest call: this warrants a MAJOR SDK bump (SDK semver is decoupled from the platform, so the platform stays on its own track). The (All prior-round findings on this PR are still open at the current head — no post-review commits landed.) |
…ULING 1)
Apply epic #2905 RULING 1 to ComputerUseGovernor so the `tool_name` audit
column means the tool name in every adapter:
- connector_type = the constant "computer_use" connector/domain marker
- tool = the tool NAME ("computer"/"bash"/"text_editor"), never the action
- the action stays in the serialized `statement` (unchanged) — it is NOT
placed in `tool`, nor in `operation` (agent-api constrains operation to
the enum {query, execute})
check_result() now sends the same identity on the response plane so request-
and response-plane rows correlate. Removes _derive_connector_type.
BREAKING: the connector_type wire value changes shape; policies scoped to the
old concatenated value (e.g. "computer_use.left_click", a bare tool name, or a
computer_use.* prefix) stop matching. Re-scope to connector_type=="computer_use"
plus the tool field. No connector_type_fn/tool_fn escape hatch on this adapter.
Requires platform v9.10.0+ to consume `tool` on check-input; check-output does
not consume it on any released version yet (#2955).
Reconciles the shared client.py/types.py/wire_shape_baseline.json hunks with
PR #216 to byte-identical, corrected text (#2916/c8df2006b merged, first
released in v9.10.0); regenerates .lint_baselines/falsey_clobber.json (CI).
Refs #2910, epic #2905.
Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
…2905)
Mark the LangGraph server/tool de-concatenation as a BREAKING change (the
connector_type wire value changes from "{server}.{tool}" to the bare server
name) and document the migration:
- Changelog: move to "Changed (BREAKING)", require a major SDK bump, add the
policy re-scope note (connector_type_fn is the compat lever), the custom-fn
statement-shape change, the missing-server fail-closed edge, and the
platform-version pins (tool consumed on check-input at v9.10.0+; check-output
tracked by #2955).
- Add the missing-server edge test: empty server_name -> connector_type=""
-> platform 400 -> ConnectorError (fail-closed); document + pin the wire.
- Reconcile the shared client.py/types.py/wire_shape_baseline.json hunks with
PR #217 to byte-identical, corrected text (#2916/c8df2006b merged, first
released in v9.10.0); thread `tool` through the check_tool_input/
check_tool_output aliases too. Declare the #216-before-#217 merge order.
- Regenerate .lint_baselines/falsey_clobber.json (line-shift only; CI green).
Refs #2906, epic #2905.
Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
…erver-tool-split Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com> # Conflicts: # .lint_baselines/falsey_clobber.json # CHANGELOG.md
Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
|
Follow-up commits (WS-DECONCAT): reconciled the shared |
|
Master independent R3: CLEAR-FOR-SET (code). Two-field split coherent with the other SDKs ( |
Bump pyproject.toml + axonflow/_version.py to 9.0.0 and finalize the tool-identity content under ## [9.0.0] - 2026-07-18 (banner dropped). The LangGraph and Computer Use de-concatenation is described in a single combined entry (byte-identical across #216/#217 — merge #216 first). Changelog scrubbed of internal issue/PR numbers and internal review terminology; minimum platform stated as versions (check-input tool = platform v9.10.0+, response-plane tool = platform v9.11.0+). Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
Bump pyproject.toml + axonflow/_version.py to 9.0.0 and finalize the tool-identity content under ## [9.0.0] - 2026-07-18 (banner dropped). The LangGraph and Computer Use de-concatenation is described in a single combined entry (byte-identical across #216/#217 — merge #216 first). Changelog scrubbed of internal issue/PR numbers and internal review terminology; minimum platform stated as versions (check-input tool = platform v9.10.0+, response-plane tool = platform v9.11.0+). Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
|
Release-ready follow-up: bumped the version to 9.0.0 and finalized the tool-identity content under a real Python: #216 and #217 share one byte-identical, combined |
|
Master re-R3 of the v9.0.0 finalize delta: CLEAR-FOR-SET. Version file 8.5.1 → 9.0.0; correct Keep-a-Changelog shape (empty |
* fix(computer-use): stop dropping tool name when action is present
_derive_connector_type(tool_name, action) discarded tool_name whenever
action was present, returning only "computer_use.{action}" — so every
actioned Computer Use tool call collapsed to the same connector_type
shape regardless of which tool (computer vs. any other actioned tool)
triggered it.
MCPCheckInputRequest/MCPCheckOutputRequest now carry a genuine two-field
(server, tool) identity contract (epic #2905, platform sub-issue #2904).
Client.mcp_check_input/mcp_check_output gain a `tool` parameter sent as
its own wire field.
_derive_connector_type is removed; ComputerUseGovernor now passes
connector_type=tool_name and tool=action directly to mcp_check_input,
so neither value is discarded. tool_name is chosen as the
connector_type-equivalent (rather than a fixed "computer_use" literal)
because it matches the rest of the SDK's convention of bare category
names for connector_type (e.g. "postgres", "snowflake") with no
namespace prefix, and because action already varies meaningfully within
a single tool (e.g. "left_click" vs "screenshot" for "computer") while
tool_name is the more stable partition key. check_result() has no
action available at its call site, so tool is left unset there,
matching its pre-existing behavior of not being able to distinguish
sub-actions on output checks.
Signed-off-by: Gregory Zak <gzak@getaxonflow.com>
* fix(computer-use)!: report (server, tool) identity, tool=tool name (RULING 1)
Apply epic #2905 RULING 1 to ComputerUseGovernor so the `tool_name` audit
column means the tool name in every adapter:
- connector_type = the constant "computer_use" connector/domain marker
- tool = the tool NAME ("computer"/"bash"/"text_editor"), never the action
- the action stays in the serialized `statement` (unchanged) — it is NOT
placed in `tool`, nor in `operation` (agent-api constrains operation to
the enum {query, execute})
check_result() now sends the same identity on the response plane so request-
and response-plane rows correlate. Removes _derive_connector_type.
BREAKING: the connector_type wire value changes shape; policies scoped to the
old concatenated value (e.g. "computer_use.left_click", a bare tool name, or a
computer_use.* prefix) stop matching. Re-scope to connector_type=="computer_use"
plus the tool field. No connector_type_fn/tool_fn escape hatch on this adapter.
Requires platform v9.10.0+ to consume `tool` on check-input; check-output does
not consume it on any released version yet (#2955).
Reconciles the shared client.py/types.py/wire_shape_baseline.json hunks with
PR #216 to byte-identical, corrected text (#2916/c8df2006b merged, first
released in v9.10.0); regenerates .lint_baselines/falsey_clobber.json (CI).
Refs #2910, epic #2905.
Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
* docs(changelog): add blank line before ### Added (MD022)
Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
* release: finalize v9.0.0 — version bump + clean [9.0.0] changelog
Bump pyproject.toml + axonflow/_version.py to 9.0.0 and finalize the
tool-identity content under ## [9.0.0] - 2026-07-18 (banner dropped). The
LangGraph and Computer Use de-concatenation is described in a single combined
entry (byte-identical across #216/#217 — merge #216 first). Changelog scrubbed
of internal issue/PR numbers and internal review terminology; minimum platform
stated as versions (check-input tool = platform v9.10.0+, response-plane tool =
platform v9.11.0+).
Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
---------
Signed-off-by: Gregory Zak <gzak@getaxonflow.com>
Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
Co-authored-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
Summary
The platform's MCP check-input/check-output schema now has a genuine two-field
(server, tool)identity contract (epic #2905, platform sub-issue #2904 — R3-approved, CI-green, not yet merged to axonflow-enterprise but the schema is finalized). Previously this SDK only hadconnector_type, which forced callers to smuggle the tool name in by concatenating it ("server.tool") or dropping it entirely.Fixes #2906 (epic #2905).
axonflow.client.Client.mcp_check_input/mcp_check_output(async and sync) gain atool: str | None = Nonekeyword-only parameter, sent as its owntoolfield on the wire body only when non-empty — same optional-field convention already used forclient_id/tenant_id/etc.MCPCheckInputRequest/MCPCheckOutputRequestpydantic models gain a matching optionaltoolfield.axonflow/adapters/langgraph.py:mcp_tool_interceptor's default connector-type resolution no longer returnsf"{server_name}.{name}". It now sendsconnector_type=request.server_nameandtool=request.nameas two separate values. This holds even when a caller supplies a customconnector_type_fn— the tool name is never folded back intoconnector_typeand is never dropped.tool_output_wrapper():ToolNode'scall_requestdict (from LangGraph'sawrap_tool_call) carries no server/origin metadata to improve on the existingconnector_typedefault (bare tool name) — confirmed by inspecting the call site; there is no tool-registry reference available to derive a better value. Rather than continue using the bare name asconnector_typewith no way to recover the tool identity, the wrapper now also sends the bare name astoolon every call, so tool identity survives explicitly instead of being implicit/ambiguous inconnector_type.MCPInterceptorOptionsdocstring and both methods' docstring examples to show the two-field form instead of the oldconnector_type_fn=lambda call: f"local.{call['name']}"pattern.tests/fixtures/wire_shape_baseline.json: acknowledgedtoolas an SDK-superset field onMCPCheckInputRequest/MCPCheckOutputRequest(mirrors the existingcontent_typeentry) until #2904 merges to axonflow-enterprise and the OpenAPI spec catches up. Per CONTRIBUTING.md's baseline burndown policy — justified rather than burned down, since it's blocked on the platform-side PR landing.Test plan
tests/test_langgraph_adapter.pyassertingconnector_typeandtoolare sent as two separate, correct values (not concatenated, not dropped) for bothmcp_tool_interceptor(default and customconnector_type_fn) andtool_output_wrapper(default and customconnector_type_fn).pytest tests/test_langgraph_adapter.py tests/test_langgraph_wrapper.py— 102 passedpytest— 1050 passed, 29 skippedruff check/ruff format --checkon changed files — cleanmypy axonflow— no new errors (one pre-existing unrelated error inheartbeat.py)