ADR-001 — Self-hosted runtime + MCP
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
- Phase 1 — Self-hosted runtime foundation. ModelProvider abstraction; in-process agent loop; deprecate Managed Agents.
- Phase 2 — MCP client integration.
@modelcontextprotocol/sdk;McpServerPrisma model + admin UI; tool router; per-MCP-tool approval gating. - Phase 3 — Additional providers. OpenAI, OpenRouter, OpenClaw (OpenAI-compatible). Per-provider cost tracking.
- Phase 4 — Migrate tools to Zapier MCP. Validate the full path: provision → wire → call → approve → result. Sunset every custom SaaS tool except
search_knowledge. - Phase 5 — Multi-tenant productisation. Tenant model + per-tenant scoping across audit / rate-limit / spend cap / vault / KB tiers;
/admin/tenantswizard;POST /api/tenants. - Phase 6 — Legacy Managed Agents path removed. Production ran on the self-hosted runtime to parity; legacy code path deleted.
USE_SELF_HOSTED_RUNTIMEflag removed.runAgentLoopis 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.
Tenantmodel +tenantIdcolumn on 13+ tables; hot-path queries scoped; cross-tenant agent-leak vectors closed. AUDIT_HMAC_SECRETmandatory in production. The platform refuses to boot without it onNODE_ENV=production.- Encrypted secrets vault. Every
Secretrow 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.