Skip to content

[AAASM-1928] ✨ (client): Add GatewayClient.dispatch_tool wrapper#60

Merged
Chisanan232 merged 3 commits into
masterfrom
v0.0.1/AAASM-1928/feat/sdk_dispatch_tool
May 24, 2026
Merged

[AAASM-1928] ✨ (client): Add GatewayClient.dispatch_tool wrapper#60
Chisanan232 merged 3 commits into
masterfrom
v0.0.1/AAASM-1928/feat/sdk_dispatch_tool

Conversation

@Chisanan232
Copy link
Copy Markdown
Contributor

Description

ST6 of Story AAASM-1920 (Secret Injection). SDK surface for the new POST /api/v1/dispatch_tool route shipped in the agent-assembly repo (AAASM-1926, #789).

Adds:

  • agent_assembly.client.DispatchToolResult — frozen dataclass with resolved_args + names_substituted.
  • GatewayClient.dispatch_tool(tool_name, args) — POSTs the placeholder-form args to the new gateway route and returns a DispatchToolResult. Maps HTTP errors (including 422 unknown-placeholder) and network failures to GatewayError.

The SDK contract complements the gateway's audit-shape contract: the wire body always carries the placeholder-form args (${NAME}); the resolved credential value lives only in the response, returned for the caller to forward to the tool sink.

Type of Change

  • ✨ New feature

Breaking Changes

  • No

Related Issues

Testing

  • Unit tests added — test/unit/client/test_dispatch_tool.py, 4 tests:
    1. success round-trip — wire body is placeholder-form, result wraps gateway response.
    2. unknown placeholder (422) → GatewayError.
    3. network failure (httpx.ConnectError) → GatewayError.
    4. defensive: empty server body → well-formed empty result.
  • .venv/bin/python -m pytest test/unit/client/test_dispatch_tool.py → 4 passed.
  • .venv/bin/ruff check + .venv/bin/ruff format --check clean on new files.
  • mypy --strict clean on agent_assembly/client/dispatch.py.

Frozen dataclass carrying the outcome of `GatewayClient.dispatch_tool`
(AAASM-1920 SDK surface):

* `resolved_args: dict[str, Any]` — post-substitution args ready to
  hand to the tool sink. Carries resolved credential values; don't log.
* `names_substituted: list[str]` — placeholder names that were
  resolved during this call (names only, never values).

Re-exported from `agent_assembly.client` alongside `GatewayClient`.

Refs AAASM-1928.
Public SDK surface for AAASM-1920 Secret Injection. POSTs
`{ tool, args }` to `/dispatch_tool`, decodes the response into a
`DispatchToolResult`, and surfaces HTTP errors as `GatewayError`.

The LLM never observes the resolved credential value: the agent code
holds the placeholder `${NAME}`, Assembly resolves it gateway-side,
and the resolved args are forwarded to the tool sink only.

Refs AAASM-1928.
Four tests pinning the SDK contract:

1. success — round-trips placeholder `${DB_PASSWORD}` args; asserts
   the result wraps the gateway's `resolved_args` +
   `names_substituted`; asserts the body sent over the wire is the
   placeholder-form (never the resolved value).
2. unknown placeholder → `GatewayError` (422 from the gateway is
   surfaced as the SDK exception type).
3. network failure → `GatewayError` (`httpx.ConnectError` maps
   through).
4. empty server response → well-formed empty result (defensive).

`.venv/bin/python -m pytest test/unit/client/test_dispatch_tool.py`
→ 4 passed; `ruff check` + `ruff format` clean.

Refs AAASM-1928.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor Author

@Chisanan232 Chisanan232 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Claude Code self-review — AAASM-1928 (ST6)

CI

  • 20 success + 4 skipped checks: all green ✅ (no failures).
  • mergeStateStatus: CLEAN. mergeable: MERGEABLE.

Scope vs Subtask ticket

AC Evidence
agent_assembly.client.DispatchToolResult — frozen dataclass with resolved_args + names_substituted agent_assembly/client/dispatch.py
GatewayClient.dispatch_tool(tool_name, args) POSTs to /dispatch_tool and returns a DispatchToolResult agent_assembly/client/gateway.py:179-218
Wire body is placeholder-form (${NAME}); resolved value lives only in the response Pinned by test 1
Re-exported from agent_assembly.client package client/__init__.py
4 unit tests: success / 422 unknown-placeholder / network error / defensive empty-response test/unit/client/test_dispatch_tool.py — 4 / 4 passed locally
.venv/bin/python -m pytest test/unit/client/test_dispatch_tool.py clean Yes
.venv/bin/ruff check + .venv/bin/ruff format --check clean on new files Yes
mypy --strict clean on dispatch.py Yes
Commit granularity — dataclass / method / tests in separate commits 3 commits

The httpx.HTTPError catch covers both 4xx (HTTPStatusError) and network failures (ConnectError) via the common parent class; the test suite proves both map to GatewayError with the tool-name-prefixed message format that matches the existing report_edge / register_agent patterns.

Verdict

Ready for merge. Independent of the agent-assembly repo PRs. No CI blockers, no semantic blockers.

@Chisanan232 Chisanan232 merged commit 75a6fa7 into master May 24, 2026
24 checks passed
@Chisanan232 Chisanan232 deleted the v0.0.1/AAASM-1928/feat/sdk_dispatch_tool branch May 24, 2026 14:17
Copy link
Copy Markdown
Contributor Author

@Chisanan232 Chisanan232 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Claude Code self-review — AAASM-1928 (ST6) — final

CI

  • 20 success + 4 skipped checks: all green ✅ (no failures).
  • mergeable: UNKNOWN — python-sdk's branch-protection rule may need a fresh check evaluation, but every actual gate passed.

Scope vs Subtask ticket

AC Evidence
agent_assembly.client.DispatchToolResult — frozen dataclass with resolved_args + names_substituted agent_assembly/client/dispatch.py
GatewayClient.dispatch_tool(tool_name, args) POSTs to /dispatch_tool and returns a DispatchToolResult agent_assembly/client/gateway.py:179-218
Wire body is placeholder-form (${NAME}); resolved value lives only in the response Pinned by test 1
Re-exported from agent_assembly.client package client/__init__.py
4 unit tests: success / 422 unknown-placeholder / network error / defensive empty-response test/unit/client/test_dispatch_tool.py — 4 / 4 passed
pytest test/unit/client/test_dispatch_tool.py clean Yes
ruff check + ruff format --check clean on new files Yes
mypy --strict clean on dispatch.py Yes
Commit granularity — dataclass / method / tests in separate commits 3 commits

Independent of the agent-assembly stack — opens against python-sdk master directly with no rebases needed. Now that the agent-assembly HTTP route (AAASM-1926, merged) is in production, the SDK surface this PR ships is wired end-to-end.

Verdict

Ready for merge. No CI blockers, no semantic blockers. Pairs with the merged AAASM-1926 (HTTP route) in the agent-assembly repo.

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.

1 participant