Agent Tool Discovery by Intent, Not by Context Injection

repoagent-loopsmcptypescriptinfrastructuretool-catalogai

mirrors the joelclaw hexagonal architecture pattern — typed catalog in front of external integrations, parallel to how inference-router wraps model selection behind a discoverable interface

Executor by Rhys Sullivan is a local-first execution environment for AI agents. You run a local daemon, connect sources — MCP servers, OpenAPI specs, GraphQL endpoints — and it indexes everything into a typed workspace tool catalog. Agents call tools.discover({ query: "github issues", limit: 5 }) at runtime to find what they need, inspect schemas, and call typed functions. The manifest doesn’t get pasted into every chat. The agent queries the catalog when it needs something.

The credentials story is the quietly important part. Secrets, OAuth flows, and auth tokens live in the local runtime and web UI — not in the agent’s context window. When a tool needs credentials, execution pauses, a local interaction record is created, you complete the flow in the browser, and the run resumes where it stopped. Human-in-the-loop without wiring it into every individual agent workflow by hand.

The tools.* namespace pattern is worth paying attention to. Sources get indexed into namespaces — tools.github.issues.list(...), tools.stripe.charges.list(...) — and the agent calls typed TypeScript functions instead of constructing raw fetch calls or hoping a shell pipeline works. The README credits Cloudflare’s Code Mode as an inspiration for the execution model. There’s also a packages/runtime-ses package in the file tree — SES (Secure ECMAScript) — which means code runs in a sandbox, not with broad shell permissions.

This maps directly onto the joelclaw hexagonal architecture (ADR-0144) — external integrations behind typed interfaces, never direct coupling. The inference-router is already a catalog for model selection. Executor extends that same idea to the full tool surface. The pattern is: catalog first, typed call second, raw access never.

Key Ideas

  • Discovery over injection: instead of pasting large MCP manifests into every agent context, agents call tools.discover({ query }) at runtime and get back ranked tool paths to inspect and call
  • Secrets stay in the daemon: credentials, OAuth tokens, and approval flows live in the local runtime UI — the agent’s context never touches secret material
  • Typed TypeScript over shell access: agents write tools.namespace.action(params) rather than raw fetch or shell commands, giving the runtime a stable structured surface to intercept and instrument
  • Pause/resume execution: when human input is needed (credentials, approvals), the run pauses and creates an interaction record — resumes cleanly with executor resume --execution-id exec_123
  • Multiple source types: MCP (streamable HTTP or SSE), OpenAPI (spec URL), GraphQL (introspected at connect time) — all normalized into the same tool catalog surface
  • SES sandbox runtime: packages/runtime-ses points to Secure ECMAScript execution, not arbitrary shell access with broad filesystem permissions
  • Dual interface: MCP endpoint for hosts that want to drive executor via MCP, plus CLI and local web UI for direct operation — executor up, executor call --file script.ts, executor status --json