Managed agents
Server-side AI with a code sandbox and durable, auditable runs. What they're for, what they can't do, and how they differ from the backend LLM.
A managed agent runs server-side under its own ratified manifest. Each run gets a code sandbox and a durable, auditable record. Managed agents are part of our paid plans. You define the agent in YAML (or JSON), and we run it.
That is the difference from an app's own llm, which runs inside one backend invocation and
is bounded by it. The backend LLM cannot outlive the request, run code, or touch a file.
When to use one
Pick the first matching row:
| The AI feature… | Use |
|---|---|
| Summarizes, classifies, or analyzes data the app already reads, while the user watches, in seconds | The app's backend llm |
| Reads, understands, extracts, summarizes, transforms, or generates any file | Managed agent (app_files + sandbox) |
| Writes and runs code | Managed agent (sandbox) |
| Is triggered outside the app (Slack, cron, API) | Managed agent |
| Must survive the request, run unattended, or needs retries | Managed agent |
| Has effects that must not depend on who is viewing | Managed agent |
| Needs a run history someone will audit or debug | Managed agent |
The file boundary is hard. An app may upload, store, list, download, and display files. But
its llm.generate() / llm.stream() must never consume file contents, file URLs, or
payloads derived from files as a substitute for an agent.
The two compose: an app keeps its chat shell in the page and hands heavy steps to an agent by
calling agents.start() from a tool's run.
The sandbox
Managed agents run in a per-run code sandbox when sandboxing is configured for the deployment. There is no manifest key or per-agent switch to request it.
The sandbox provides shell and file tools. The agent can write and run code, inspect and transform files, and use the libraries the job needs: parsing Excel or CSV data, extracting or assembling PDFs, editing documents, extracting archives, and producing artifacts.
The sandbox is ephemeral. It carries no credentials and no standing org access. Tenant files
come in through app_files. Other systems are reachable only through explicit manifest
authorities. Durable outputs leave through app_data_write. Anything left only in the
sandbox disappears when the run ends.
Visibility
Every agent is org or personal. The choice is not reversible in both directions.
org (default) | personal | |
|---|---|---|
| Who can invoke | Anyone with an invoke grant | The creator alone, admins included |
| Who can manage | The creator, or any org owner/admin | The owner alone, no admin override |
| Writes land in | The app's shared scope | The owner's user scope |
personal_connectors | Not allowed | Required for it |
| Creating needs | agent:create_org | agent:create |
personal → org is rejected outright. org → personal is allowed, but it does not
retroactively change past shared runs or writes.
Pick personal only when the agent needs its owner's own Gmail, Slack, or similar, or when
exactly one person should use it.
Prefer an org agent when it pairs with an app. An org agent's writes land in the app's shared scope, which is the app's flat store. Results appear in a collection the backend function already reads, with no bridge.
Slack
Once an org admin has connected the org's Slack workspace, every active agent is reachable from Slack with no per-agent setup:
@Railcode $<agent-name> summarize this threadThe agent name takes a leading $ and must be the first token after the mention.
- Authority is unchanged. The platform resolves the Slack caller by verified email to a
live org member. That member must hold the normal invoke grant. A
personalagent is reachable on Slack only by its owner. - Input arrives as
{ text: <message> }. Agent input is free-form, so any agent can be mentioned. Its system prompt must explain how to interpret that. - The platform posts the final reply into the mentioning thread, on success and on
failure. Whatever the agent returns is the Slack reply. It does not need the
slackconnector to answer. That connector, when granted, is for interim progress updates only.
So any agent a team will use conversationally should handle free-text input and produce a final answer that reads well as a Slack message.
Hard limits
What a managed agent cannot do, regardless of manifest:
- Reach the open web. Sandbox egress is an allowlist (PyPI, npm, and the presigned
download host with
app_files). Theconnectortool reaches only ratified endpoints. It cannot scrape pages or call arbitrary APIs. - Run long or continuously. Runs are bounded to at most 300 steps, 1200 seconds, and the
token caps in
limits. There are no daemons or monitors. Recurring work is a cron schedule. - React to events. Triggers are app/API call, cron, and Slack mention only. There are no data-change or inbound-webhook triggers.
- Invoke other agents. There is no agent-to-agent tool. Compose pipelines through an app or an external caller.
- Use custom MCP connectors. A user-added by-URL MCP connector works for its owner and for apps, but it is not declarable in an agent manifest, because ratification checks the static registry. Bundled toolkits only.
- Keep sandbox state. The filesystem is per-run. Anything worth keeping must be published or written to KV before the run ends.
Where to go next
- Manifest and tools: the
toolsvocabulary andlimits. - Building an agent: scope, test, publish, verify, schedule.
- Companion apps: the app-plus-agent pattern most agent work takes.