ADR-001 — Self-hosted runtime + MCP

Shipped 2026-05-23. All five phases landed; legacy Managed Agents code path deleted in Phase 6 the same day.

Context

Aroovo originally shipped on Anthropic Managed Agents (Way 2). It was the right starting point — Anthropic ran the agent loop, the session state, and the tool dispatch — while we focused on the operator console, audit chain, approvals, hierarchical routing, and the Teams integration. The Managed Agents ceiling showed up the moment we wanted multiple model providers, a single integration layer that scaled to dozens of SaaS tools, and clean multi-tenant onboarding.

Decision

Build the agent runtime in-process. Adopt the Model Context Protocol as the long-term integration layer; use Zapier MCP for breadth (roughly 6,000 services through one endpoint). Make the runtime provider-pluggable so each agent can pick Anthropic, OpenAI, OpenRouter, OpenClaw, or any future provider.

Phases

  1. Phase 1 — Self-hosted runtime foundation. ModelProvider abstraction; in-process agent loop; deprecate Managed Agents.
  2. Phase 2 — MCP client integration. @modelcontextprotocol/sdk; McpServer Prisma model + admin UI; tool router; per-MCP-tool approval gating.
  3. Phase 3 — Additional providers. OpenAI, OpenRouter, OpenClaw (OpenAI-compatible). Per-provider cost tracking.
  4. Phase 4 — Migrate tools to Zapier MCP. Validate the full path: provision → wire → call → approve → result. Sunset every custom SaaS tool except search_knowledge.
  5. Phase 5 — Multi-tenant productisation. Tenant model + per-tenant scoping across audit / rate-limit / spend cap / vault / KB tiers; /admin/tenants wizard; POST /api/tenants.
  6. Phase 6 — Legacy Managed Agents path removed. Production ran on the self-hosted runtime to parity; legacy code path deleted. USE_SELF_HOSTED_RUNTIME flag removed. runAgentLoop is the sole execution path.

Security + tenancy hardening pass

A same-day follow-up pass closed the operational gaps:

  • Lazy provider init. Missing optional provider keys no longer break Anthropic-only deploys.
  • Multi-tenant scaffolding. Tenant model + tenantId column on 13+ tables; hot-path queries scoped; cross-tenant agent-leak vectors closed.
  • AUDIT_HMAC_SECRET mandatory in production. The platform refuses to boot without it on NODE_ENV=production.
  • Encrypted secrets vault. Every Secret row AES-256-GCM-encrypted; unique on (tenantId, name).
  • MCP arg validation. Ajv-compiled validators per (server, tool); invalid args never hit the upstream Zap.
  • Per-tenant rate limit + spend cap + audit verify. Compromised seat in one Tenant can't burn another's quota.
  • SSRF protection on MCP bootstrap. Hostname allowlist + private IP block + loopback name blocks.
  • Console security headers. HSTS preload, X-Frame DENY, CSP that allows MSAL + the bot host only.

Consequences

Positive. Multi-provider per-agent choice; cost optimisation (cheap models for routing, frontier for synthesis); vendor diversification; one integration layer for new tools; multi-tenant ready; Anthropic org migration becomes trivial; tests get easier (mock ModelProvider).

Negative. Largest blast radius change since the original Managed Agents adoption. Prompt caching becomes manual. Anthropic Skills no longer available. ~500-1000 net new lines of code. Streaming UX needed explicit re-implementation.

References

Full markdown: adr-001-self-hosted-runtime-mcp.md.

Related: ADR-003 Brand layer, Concepts — MCP tools, Concepts — Security model.