Skip to content

feat(dev): Agent Inspector agent-proxy routes (C2) - #2085

Open
tejaskash wants to merge 2 commits into
feat/inspector-http-layerfrom
feat/inspector-agent-proxies
Open

feat(dev): Agent Inspector agent-proxy routes (C2)#2085
tejaskash wants to merge 2 commits into
feat/inspector-http-layerfrom
feat/inspector-agent-proxies

Conversation

@tejaskash

Copy link
Copy Markdown
Contributor

What

PR C2 of the Agent Inspector stack (C1 = #2082). Adds every Inspector route that talks to a running agent or reads the project spec, extending C1's route table. Still not reachable from the CLI; wiring lands in C3.

Stacks on feat/inspector-http-layer (C1). Re-authored against current refactor APIs using feat/agent-inspector as the reference.

Routes

  • POST /invocations — protocol-aware proxy for HTTP, A2A, and AGUI agents, each normalized into the SPA's data: <json> SSE contract. MCP agents get an explicit error pointing at /api/mcp instead of being mis-proxied as HTTP.
  • POST /api/mcp — forwards a JSON-RPC body to the agent's /mcp endpoint, buffering the reply under a 10MB cap.
  • GET /api/a2a/agent-card — fetches the running agent's A2A card.
  • GET /api/resources — flattens project.spec into the resource graph the SPA renders.

Reviewer preempts addressed

  • MCP invocation arm returns a clear "use /api/mcp" error rather than falling through to HTTP.
  • Abort propagation. Every upstream fetch carries the client request's AbortSignal. io/httpServer now streams async-iterable bodies with backpressure and aborts a controller on the response close event, so on Node (the published runtime) a browser disconnect tears the upstream request down. Bun's node:http does not surface mid-stream disconnects; that limitation is documented inline (dev-only leak of a local fetch until it finishes).
  • Robust SSE parsing. sseData follows the framing rules (optional leading space after data:, multi-line data: fields, blank-line event boundary) and never forwards unparsable payloads as content. The hardcoded slice(6) is gone.
  • Single session id threads through the request header, agent body, and echoed x-session-id.
  • MCP proxy advertises Accept: application/json only (it buffers, never streams) and enforces a body-size cap.
  • A2A dedup ordering covered by a test for a status-update preceding an artifact-update with the same text.

Tests (both altitudes)

  • invocations.test.ts — routing (409, MCP arm), SSE normalization (test.each over event shapes), error frames, non-SSE passthrough, single-session-id forwarding, A2A message/stream translation + dedup + non-streaming fallback, AGUI RunAgentInput.
  • proxies.test.ts — MCP forward, 400s (test.each), not-running, upstream error, body-cap 502; agent-card happy/missing-param/unavailable.
  • resources.test.ts — resource graph happy path + no-project 404.
  • httpServer.test.ts — async-iterable streaming and a deterministic stream() abort-honoring unit test (real socket disconnect is not observable under bun test).

bun test (1841 pass), bun run typecheck, bun run lint:check, bun run format:check all green.

@github-actions github-actions Bot added the size/xl PR size: XL label Aug 24, 2026
@github-actions github-actions Bot added agentcore-harness-reviewing AgentCore Harness review in progress and removed agentcore-harness-reviewing AgentCore Harness review in progress labels Aug 24, 2026
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 24, 2026
Add the Inspector routes that talk to a running agent or read the
project spec, extending the C1 route table:

- POST /invocations proxies HTTP, A2A, and AGUI agents, normalizing each
  into the SPA's data:<json> SSE contract. MCP agents get a clear error
  directing them to /api/mcp rather than being mis-proxied as HTTP.
- POST /api/mcp forwards a JSON-RPC body to the agent's /mcp endpoint and
  buffers the reply under a 10MB cap.
- GET /api/a2a/agent-card fetches the running agent's A2A card.
- GET /api/resources flattens the project spec into the resource graph.

Every upstream fetch carries the client's abort signal, and io/httpServer
streams async-iterable bodies with backpressure so a disconnect tears the
upstream request down on Node. A single session id threads through the
request header, agent body, and echoed x-session-id.

SSE parsing follows the framing rules (optional leading space, multi-line
data fields, blank-line event boundary) instead of a hardcoded slice.
- collapse invokeHttpAgent/invokeAguiAgent into a shared forwardInvocation
- single-return parseAgentEvent normalizing empty payloads to null
- hoist the SSE TextEncoder to module scope
- readCapped iterates over the shared iterateBody helper
- drop the a2aId counter; A2A message ids use randomUUID
- add the AGUI missing-prompt test
@tejaskash
tejaskash force-pushed the feat/inspector-http-layer branch from e59cda5 to 1b3491b Compare August 25, 2026 17:35
@tejaskash
tejaskash force-pushed the feat/inspector-agent-proxies branch from fcff328 to 013ffe2 Compare August 25, 2026 17:35
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant