Skip to content

fix(computer-use): stop dropping tool name when action is present#217

Merged
saurabhjain1592 merged 5 commits into
mainfrom
feat/2910-computer-use-tool-name-fix
Jul 17, 2026
Merged

fix(computer-use): stop dropping tool name when action is present#217
saurabhjain1592 merged 5 commits into
mainfrom
feat/2910-computer-use-tool-name-fix

Conversation

@gzak

@gzak gzak commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

_derive_connector_type(tool_name, action) in axonflow/adapters/computer_use.py discarded tool_name whenever action was present, returning only f"computer_use.{action}". Every actioned Computer Use tool call (e.g. computer with action="left_click") collapsed to the same connector_type shape regardless of which actual tool triggered it — connector_type couldn't distinguish tool identity for any actioned tool.

Fixes #2910 (epic #2905). Uses the platform's two-field (server, tool) identity contract (platform sub-issue #2904, merged to axonflow-enterprise as c8df2006b and first released in platform v9.10.0).

Design decision (epic #2905, RULING 1)

Per RULING 1 on the epic, tool carries the tool name in every adapter so the tool_name audit column means the same thing regardless of which adapter emitted it. There were three pieces of information: the "computer_use" domain marker, tool_name ("computer"/"bash"/"text_editor"), and action ("left_click"/"screenshot", present only for some tools). They map as:

  • connector_type = the constant "computer_use" — the connector/domain marker, analogous to the LangGraph adapter's connector_type = server_name. Restoring "computer_use" as the connector value also keeps computer_use-scoped policies matchable on connector_type.
  • tool = tool_name (e.g. "computer") — the tool NAME, never the action. This is what makes the identity coherent with the LangGraph adapters (where tool is also the tool name).
  • action stays in statementjson.dumps(tool_input) already serializes the action key, and the policy engine evaluates the statement. The action is not placed in tool, and not in operation: operation is a spec-declared enum {query, execute} in agent-api.yaml, so putting "left_click" there would violate our own published contract. operation stays "execute".

_derive_connector_type is removed. check_result() sends the same identity on the response plane (connector_type="computer_use", tool=tool_name) so request- and response-plane rows correlate — the platform doesn't yet consume tool on check-output (#2955), so it is sent forward-compatibly.

This is a breaking change (the connector_type wire value changes shape) and must ship as a major SDK bump; this adapter has no connector_type_fn escape hatch, so re-scoping policies is the only migration path — see the CHANGELOG.

Also (shared with #2906, byte-identical hunks — merge #216 first):

  • mcp_check_input/mcp_check_output (and the check_tool_input/check_tool_output aliases), async and sync, gain an optional tool: str | None = None parameter, sent on the wire only when non-empty.
  • MCPCheckInputRequest / MCPCheckOutputRequest gain a matching optional tool field.
  • tests/fixtures/wire_shape_baseline.json acknowledges tool as an SDK-superset field on both request models (the public agent-api.yaml spec hasn't declared it yet, though the agent consumes it on check-input since v9.10.0).

Test plan

  • Rewrote TestConnectorTypeToolSplit to assert the RULING-1 mapping: connector_type == "computer_use" (constant) and tool == the tool name for actioned and non-actioned tools; that two calls to the same tool with different actions carry the same (connector_type, tool) identity while the differing action lives in statement; and that operation stays "execute" (spec-compliant, action never smuggled in).
  • Updated TestCheckToolUse / TestCheckResult assertions to the new mapping (connector_type="computer_use", tool=tool name on both planes).
  • Rewrote runtime-e2e/computer_use_tool_name_split/test.py for the new mapping (wire-body capture against a live agent; action asserted present in statement).
  • pytest tests/test_computer_use.py — 30 passed; full suite — 1052 passed, 29 skipped.
  • ruff check / ruff format --check on changed files — clean; mypy axonflow — no new errors.
  • Regenerated .lint_baselines/falsey_clobber.json (line-shift only). Merged origin/main (the caller_name legs) in non-destructively; CI green, MERGEABLE/CLEAN.

@gzak
gzak force-pushed the feat/2910-computer-use-tool-name-fix branch from d923bc9 to fae0a85 Compare July 16, 2026 22:45
_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>
@gzak
gzak force-pushed the feat/2910-computer-use-tool-name-fix branch from fae0a85 to 92fb7cf Compare July 16, 2026 22:51
@saurabhjain1592

Copy link
Copy Markdown
Member

R3 review (master + independent hostile pass). The core fix is verified correct — previously _derive_connector_type discarded the tool name whenever an action existed; now both survive, with good unit + live-wire coverage (actioned/non-actioned/same-tool-different-action/check_result). Must-fix:

BLOCKER — CI is red

lint fails (run 29540706653) with 12 NEW falsey-clobber findings, mostly in files this PR doesn't touch (client.py:1682/1723/1781/2299, computer_use.py:175/209) — line-number baseline drift. Regenerate .lint_baselines/falsey_clobber.json in this PR.

MEDIUM — semantic drift needs an epic-level ruling before merge

This PR sends tool = ACTION (left_click) with connector_type = tool name (computer, bash), while the four langgraph PRs send tool = tool name. On a new platform, audit rows here read tool_server="bash" / tool_name="left_click"bash is not a server, and the meaning of the tool_name audit column now depends on which adapter emitted it. If intended, record the decision on epic #2905; if not, tool should carry the tool name and the action belongs elsewhere (e.g. operation/statement).

MEDIUM — stale contract claims + #216 collision

wire_shape_baseline.json note + types.py comment say #2904 is "not yet merged" — it merged 2026-07-16 (enterprise c8df2006b). Update, and reconcile with #216's edits to the same lines (guaranteed conflict; #216's text is the correct one).

MEDIUM — hard policy break with no escape hatch

connector_type loses the computer_use. namespace entirely (computer_use.bashbash) on EVERY platform version, so existing policies/per-connector settings scoped to computer_use.* stop applying — and this adapter has no connector_type_fn escape hatch. The changelog migration note is the only mitigation; it's currently absent. Add it (Go #189 has the model text).

@saurabhjain1592

Copy link
Copy Markdown
Member

Delta note — semver (net-new, strongest case in the cluster). This drops the computer_use. namespace from connector_type entirely (computer_use.bash -> bash) on every platform version, so all existing computer_use.*-scoped policies and per-connector settings silently stop applying — and this adapter has no connector_type_fn escape hatch to restore the old value. That is a textbook incompatible behavioral change with no migration lever: MAJOR bump required, or add an escape hatch. Current changelog (### Fixed, no migration note) materially understates it.

Also still open at head: CI is RED (falsey-clobber baseline line-drift, 12 new + 12 stale — baseline never regenerated in-PR); the tool=ACTION vs tool-name semantic still needs the epic ruling (item 3 on the #2905 roll-up — no ruling posted yet); the "#2904 not yet merged" comments are now stale (#2916 shipped in v9.10.0).

…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>
saurabhjain1592 added a commit that referenced this pull request Jul 17, 2026
…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>
…e-tool-name-fix

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>
@saurabhjain1592

Copy link
Copy Markdown
Member

Follow-up commits (WS-DECONCAT): applied epic #2905 RULING 1connector_type="computer_use" (constant), tool=the tool NAME (computer/bash/text_editor, never the action). The action is NOT put in tool and NOT in operation (agent-api constrains operation to the enum {query,execute}) — it stays in the JSON statement, which already carried it. check_result sends the same identity. _derive_connector_type removed. Reconciled the shared client/types/baseline hunks with #216 (byte-identical) and regenerated the falsey_clobber baseline. Changelog is Changed (BREAKING) (major bump, no connector_type_fn escape hatch on this adapter — called out, computer_use.* namespace-loss migration note, min-platform pins). Merge #216 first. Merged main in. CI green, MERGEABLE/CLEAN, master-R3'd. Ruling recorded on #2905.

@saurabhjain1592

Copy link
Copy Markdown
Member

Master independent R3: CLEAR-FOR-SET (code). RULING 1 verified correct: connector_type="computer_use", tool=tool name, action stays in statement (pinned by test_tool_name_survives_regardless_of_action). The operation-enum reasoning is TRUE — agent-api.yaml operation is enum:[query,execute], so the action can't go there; adapter sets operation="execute". Namespace-loss/no-escape-hatch BREAKING changelog prominent; shared hunks byte-identical with #216; CI green; non-destructive.

MEDIUM (non-code) — update this PR's description. The body still describes the PRE-RULING-1 mapping (connector_type=tool_name, tool=action, "different actions → different tool values") — the exact inversion the shipped code overturned. Code/tests/CHANGELOG are all correct; only the description is stale and would mislead a reviewer trusting it. Fix before merge.

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>
saurabhjain1592 added a commit that referenced this pull request Jul 17, 2026
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>
@saurabhjain1592

Copy link
Copy Markdown
Member

Release-ready follow-up: bumped the version to 9.0.0 and finalized the tool-identity content under a real ## [9.0.0] - 2026-07-18 changelog header (dropped the "must be a major bump" banner — the header is the bump). Scrubbed the [9.0.0] changelog of internal issue/PR numbers and internal review terminology; minimum platform is now stated as versions (check-input tool = AxonFlow platform v9.10.0+, response-plane tool = v9.11.0+). Version-alignment gate green. CI green, MERGEABLE/CLEAN. Master-R3'd (2 rounds, incl. an independent finalization pass).

Python: #216 and #217 share one byte-identical, combined [9.0.0] de-concat entry — merge #216 first. (PR description also rewritten to the shipped mapping.)

@saurabhjain1592

Copy link
Copy Markdown
Member

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 [Unreleased] above ## [9.0.0], BREAKING content under [9.0.0], release-workflow preflight will match). Public [9.0.0] block scrubbed clean — no enterprise issue/PR numbers, no RULING language, min-platform stated as versions (v9.10.0+/v9.11.0+). Finalize commit is additive; de-concat logic (two-field split + rulings) untouched. CI green.

saurabhjain1592 added a commit that referenced this pull request Jul 17, 2026
)

* fix(langgraph): stop concatenating server/tool into connector_type

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>

* fix(langgraph)!: de-concatenate server/tool as breaking major (epic #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>

* 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>
@saurabhjain1592
saurabhjain1592 merged commit 516c47f into main Jul 17, 2026
18 checks passed
@saurabhjain1592
saurabhjain1592 deleted the feat/2910-computer-use-tool-name-fix branch July 17, 2026 23:23
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