camelRun by camelAI
Multi-tenant AI agents
Give every user of your SaaS app an AI agent of its own. camelRun runs them all and tells your tools which user each call is for.Give every user of your SaaS app, or every conversation, an AI agent of its own. camelRun runs them all, wakes each one when its user writes, and tells your tools which user each call is for.
thread-4127: new agent
Agent keys
One AI agent per user
Upsert an agent with an id from your own app on every request: a user, a thread, a whole customer. The same key is the same agent from any process, with its own history and files. Who it acts for is set with your API key, and neither the agent's own token nor the model can change it. camelRun runs thousands of agents at once.
import { Agents } from "@camelai/run";
const agents = new Agents(); // CAMELAI_API_KEYconst agent = await agents.upsert(`thread-${thread.id}`, {
definition: SUPPORT_DEFINITION, // tools served by your backend, see below
subject: thread.ownerId, // whom the agent acts for
context: { org: thread.orgId }, // claims your tools authorize against
});
const run = await agent.run(message, { user: currentUser.id });Served tools
Every tool call says which user it's for
Serve your tools once, from your own backend. camelRun signs every call with a token that names the agent and who is acting, so one endpoint answers every user's agents. Your code authorizes from that identity, never from the model's arguments.
A call from another camelRun account's agent is turned away before your tool runs, whatever user it claims.
- get_assignmentuser-123 · org_abc123200
- list_todosuser-456 · org_abc123200
- get_assignmentuser-311 · org_q81x7d200
- get_assignmentuser-123 · another account401
- identity.user
- "user-123"
- identity.context
- { org: "org_abc123" }
import { schema, tool } from "@camelai/run";import { serveTools } from "@camelai/run/server";const tools = {
list_todos: tool({
description: "The current user's to-dos", input: schema.Object({}),
execute: (_args, { identity }) => db.todos({ user: identity!.user, org: identity!.context.org }),
}),
};
// tenant: yours (GET /v1/me). Other tenants' agents can reach this URL too, claiming any user: their tokens are refused.
export default { fetch: serveTools(tools, { runtime: "https://run.camelai.com", tenant: "acme" }) };const definition = await agents.runtime.upsertDefinition("support", {
name: "Support",
mcpServers: [{ name: "app", url: "https:/ / app.example.com/ mcp", auth: { type: "runtime" } }],
});Browser tokens
Let each user watch their agent in the browser
Your server mints a short-lived browser token for each user, after its own access check. Their browser reads that one agent straight from camelRun: messages as they stream, tool progress, older history. It never holds your API key, and your server relays nothing.
Lab report: plant growth
user-123Can you check my lab report intro? It's due Friday.
- GET200stream/v1/agents/client_9c41e7d2/events
- GET200/v1/agents/client_9c41e7d2/history
- DELETE403/v1/agents/client_9c41e7d2
// POST / api/ threads/ :id/ token, after checking the user may see this thread
const agent = await agents.upsert(`thread-${threadId}`, config);
return Response.json(await agents.runtime.browserToken(agent.id, { ttlSeconds: 900 })); // { token, expiresAt, agentId, url }Key scopes
Let each customer bring their own LLM API key
A per-customer key scope holds that customer's own provider keys. Their agents call the model with them, and camelRun charges $0 for tokens on their keys. Change a key, and every agent in the scope uses the new one from its next call.
Spend limits cap what each agent spends on models, and end-user credits let you charge your users for it.
FAQ
Questions about multi-tenant AI agents
How do I give every user their own AI agent?
Upsert an agent keyed by an id from your app, such as user-123 or thread-4127, on each request. The first call makes the agent and every later call returns the same one, with its history and files. Set subject and context when it's made, and your tools learn who it acts for.
How do I keep each customer's data separate?
Each agent keeps its own history and files, and your tools authorize every call within the customer named in its context. Your account is walled off from every other camelRun account: one can't list, read, prompt, inspect or delete another's agents. For data that must stay on your own servers, self-host the open-source runtime.
Can each customer bring their own model API key?
Yes. A key scope per customer holds that customer's provider keys, and their agents call providers with them. An agent without a scope uses your account's own keys, or camelAI's if you haven't added any.
Can the browser talk to an agent without my API key?
Yes. A browser token lets one user's browser read one agent directly: its live stream, state, history and the questions it waits on. Their messages and answers go through your server, which checks the user first, so your API key never leaves it.
How does it scale to thousands of users?
It runs thousands of agents at once, and most agents in a multi-tenant app sleep between messages. Sleeping agents cost only storage, so making one for every user stays cheap.
Can I cap what each user's agent spends?
Yes. A spend limit caps one agent's model spend, and setting it starts the count from zero, so you can give a user their remaining allowance before each run. Usage webhooks then let you meter every user.
Can I delete a user's agent and everything in it?
Yes. Delete it with your API key, and its history and workspace are purged. An agent for a chat can also expire on its own once nobody has written to it for a while.
More on per-user AI agents
Start building
Give your first user an AI agent
Get an API key, upsert an agent with your user's id, and serve it your tools. The guides cover identity, browser tokens and key scopes.
Read https://run.camelai.com/SKILL.md and set up camelRun in this project. Ask me what the agent should do.
Paste into Claude Code, Codex, Cursor or any coding agent. It asks what your agent should do, then builds it.