Skip to main content
@personaai/runtime’s routes split into two trust tiers, and this is a deliberate design choice, not an oversight:
  • Always on — things an end user does in their own chat session: send messages, manage their own conversations/files/memory, connect their own MCP account. Scoped entirely to whichever user resolveUser returns for that request.
  • Opt-in via capabilities — Project-level configuration: LLM provider credentials, skill authoring, knowledge base and vector store management, security audit logs, an agent-building co-pilot, and full Agent/MCP-server CRUD. Every one of these defaults to false. Upgrading this package never silently exposes new surface to whoever resolveUser accepts.

The capability flags

Each flag gates exactly the routes listed against it in the Routes opt-in table. GET /agents (read-only discovery) is always on regardless of agentsWrite — only the write/mutate routes need the flag.
providers is the one to think hardest about: enabling it exposes routes that create/update/ read LLM provider credentials (API keys) for your Project. Only enable it on a mount that resolveUser locks down to your own team.

Who should enable these

Most hosts should never turn any of these on. The intended pattern is to call @personaai/sdk directly from your own admin backend, CLI, or setup script for Project configuration — that’s what “belongs to the host application” means in practice. This runtime’s job is the end-user-facing surface (/chat, /threads, /files, /memory), not necessarily your team’s internal tooling.

The two-mount pattern

If you do want an admin surface reachable over HTTP — e.g. building your own internal admin tool on top of this runtime — the right pattern is two separate createRuntime() calls mounted at two different paths, each with its own resolveUser:
resolveAdminUser is where the actual access control lives — e.g. checking a role claim on the session, or a hardcoded allowlist of internal user ids. The runtime itself doesn’t know what “admin” means; it only knows whether a given mount’s capabilities are on or off.

Coarse-grained by design

This is intentionally coarse: a capability is either fully on or fully off for whoever resolveUser accepts on that mount. There is no per-user or per-action permission model inside the runtime itself — “this user can update Agents but not delete them” isn’t expressible as a capability flag. If you need that level of granularity, enforce it in resolveUser (reject the request before it reaches the route) or in a lifecycle hook (e.g. throw from beforeRun for a disallowed action), not by asking this runtime for finer-grained capability flags than “on this mount, for this resolved identity, is the capability on.”