Skip to content

feat: remote agents - #63

Draft
maxy-shpfy wants to merge 1 commit into
07-01-refactor_extract_ui-extensions-sdkfrom
07-17-feat_remote_agents
Draft

feat: remote agents#63
maxy-shpfy wants to merge 1 commit into
07-01-refactor_extract_ui-extensions-sdkfrom
07-17-feat_remote_agents

Conversation

@maxy-shpfy

@maxy-shpfy maxy-shpfy commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

TL;DR

Introduces remote and external sub-agent hosting, a generic MCP relay, and the @tangent/remote-subagent connector SDK so sub-agents can run outside the local pi process.

What changed?

Remote sub-agent transport (RemoteEnvironmentGateway)

  • Added a dedicated Socket.IO namespace (/remote-env) that a remote environment authenticates against using REMOTE_ENV_TOKEN.
  • RemoteEnvironmentGateway exposes the same spawnSubagent / sendToAgent / killAgent / listSubagents / hasAgent surface as PiAgentManager, so the internal agents API can route a sub-agent to either host transparently.
  • Inbound streamed events are relayed through the same PiAgentHandlers a local sub-agent uses; finalized auto-relay replies and message_prime-style reports are fed into Prime via a deliverToPrime callback.
  • Remote sub-agents are persisted with host: "remote" and are skipped by reviveSubagents on restart.

External sub-agent gateway (ExternalSubagentGateway)

  • In-memory registry for sub-agent tabs whose work runs entirely outside Tangent (e.g. driven by a bundle tool). A bundle registers a tab, streams events into it, and marks its lifecycle via POST /internal/external-agents/{register,event,status}.
  • Shares the same PiAgentHandlers relay path as local and remote sub-agents.

Generic MCP relay (RelayRegistry + McpRelayServer)

  • RelayRegistry manages ephemeral relay channels, each bound to a session and protected by a per-channel bearer secret.
  • McpRelayServer speaks the MCP JSON-RPC subset an external client exercises (initialize, tools/list, tools/call) and exposes two tools — send_to_prime (fire-and-forget) and ask_prime (blocking poll up to 25 s) — that forward to the channel's session Prime.
  • Bundle extensions open channels via POST /internal/mcp-relay/open (requires TANGENT_PUBLIC_URL), poll/answer pending questions, and close channels. The external client dials POST /api/mcp/:channelId with its per-channel bearer.

@tangent/remote-subagent package

  • New connector SDK that manages the Socket.IO connection to the gateway, dispatches spawn / message / kill commands to user-supplied handlers, and exposes typed helpers (agentEvent, subagentUpdate, report, readRoom, disconnect). Ships no agent runtime.

Shared contracts (@tangent/shared)

  • Added SubagentHost type ("local" | "remote") and host field on SubagentInfo.
  • Added remoteSubagent.ts with all wire shapes (RemoteEnvHandshake, RemoteEnvEvents, RemoteSpawnCommand, RemoteMessageCommand, RemoteKillCommand, RemoteAgentEvent, and payload/response types) shared by both sides of the transport.

spawn_subagent orchestrator tool

  • Added an environment parameter (local | remote) that flows through POST /internal/agents/spawn and routes the spawn to the appropriate host.

Database

  • Migration 0005_quick_lifeguard adds a host column (default 'local') to session_agents.

Sub-agent roster

  • handleChatJoin and the internal agents list endpoint now merge local, remote, and external rosters before emitting to the UI.

How to test?

  1. Remote sub-agents: Set REMOTE_ENV_TOKEN to a shared secret. Connect a remote environment using connectRemoteEnvironment from @tangent/remote-subagent with matching credentials. Ask Prime to spawn_subagent with environment: "remote" and verify the tab appears in the sidebar and streams events correctly. Disconnect the environment and confirm active remote sub-agents transition to error.

  2. External sub-agents: From a bundle tool, call POST /internal/external-agents/register to create a tab, then POST /internal/external-agents/event to stream events into it, and POST /internal/external-agents/status to mark it complete. Verify the tab renders and updates in the sidebar.

  3. MCP relay: Set TANGENT_PUBLIC_URL to a reachable base URL. Open a channel via POST /internal/mcp-relay/open. Point an MCP client at the returned url with the returned secret as a bearer token. Call tools/list and tools/call for send_to_prime and ask_prime. Verify messages arrive in Prime and that ask_prime resolves after answering via POST /internal/mcp-relay/:channelId/answer.

  4. Unit tests: Run the new test files externalSubagentGateway.test.ts and relayRegistry.test.ts with node --test.

  5. Restart resilience: Spawn a remote sub-agent, restart the server, and confirm it is not revived (unlike local sub-agents).

Why make this change?

Local pi child processes are the only sub-agent host today, which limits where agent work can run. This change decouples the sub-agent interface (roster, streaming events, relay to Prime) from the runtime, enabling three new hosting modes: a connected remote environment (for agent runtimes that live outside the server process), an external bridge (for bundle tools that drive a proprietary runtime and only need a sidebar tab), and a generic MCP relay (for external clients that speak standard MCP and need to communicate with Prime). All three share the same relay handlers and persistence path as local sub-agents, so the UI and storage layers require no per-host changes.

maxy-shpfy commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@maxy-shpfy
maxy-shpfy force-pushed the 07-17-feat_remote_agents branch from 61faaff to 7ce539e Compare August 20, 2026 22:51
@maxy-shpfy
maxy-shpfy force-pushed the 07-01-refactor_extract_ui-extensions-sdk branch from ba826b5 to 844886d Compare August 20, 2026 22:51
This was referenced Aug 20, 2026
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