camelAI Documentation

API Reference

SDKs

The TypeScript and Python SDKs: Agents, upsert, run, stream, tools and the lower-level API

npm install @camelai/run   # Node 22+, Bun, Deno, Cloudflare Workers
TypeScript entry
@camelai/runEverything portable: Agents, tool, schema, the lower-level AgentRuntime and AgentClient, and the types
@camelai/run/nodeThe same for Node and Bun, plus local file paths as attachments and nodeListener
@camelai/run/serverserveTools, verifyRuntimeToken, runtimeAuth, runtimeIdentity, createAgentHandler
@camelai/run/watchwatchAgent, for reading an agent from a browser
@camelai/run/chatcreateAgentChat, the framework-free chat store
@camelai/run/ai-sdkAgentRuntimeChatTransport, for the AI SDK's useChat
@camelai/run/mcpfromMcpServer, for attaching an MCP SDK server
@camelai/run/testingtestRuntime, for signing identity tokens in tests

Agents

const agents = new Agents({ apiKey, url }); // or `await using agents = new Agents()`
  • apiKey defaults to CAMELAI_API_KEY, and url to CAMELAI_BASE_URL, else https://run.camelai.com.
  • agents.close() closes every agent's connection so the process can exit. Their runs go on in camelRun.
  • agents.runtime is the lower-level AgentRuntime: definitions, volumes, listAgents(), browserToken(agentId), inbox() and toolSources(agentId).

agents.upsert(key, config)

The agent for key, made if there's none and brought to config if it differs. Returns a connected Agent.

TypeScriptPython
modelmodel="provider/model-id" from GET /v1/models
instructionsinstructions=The system prompt
instructionsAppendinstructions_append=Text after the prompt, such as per-conversation context
toolstools=Tools served from this process: { name: tool({...}) }, or a list of @tool functions
builtinsbuiltins=web_search, web_fetch, schedule, ask_user
definitiondefinition=Make it from a definition
thinkingLevelthinking_level=off, minimal, low, medium, high, xhigh, max
subject, contextsubject=, context=Whom it acts for, and claims for its tools. Fixed at creation
keyScope, spendLimit, modelHeaderskey_scope=, spend_limit=, model_headers=See Models and keys
mounts, fileToolsmounts=, file_tools=Its volumes (fixed at creation), and whether it has file tools
namename=A label shown in the console
attachattach=false: declare tools without serving them
takeovertakeover=Replace the process serving the tools now
onEvent, onInput, onErroron_event=, on_input=, on_error=Callbacks for events, inputs as they're asked, and connection errors

Agent

TypeScriptPython
agent.idagent.idclient_..., safe to log and store
agent.run(text, options)await agent.run(text, ...)Send a message and wait for the Run
agent.stream(text, options)agent.stream(text, ...)The run as it happens: for await / async for over parts
agent.pendingInputs()pending_inputs()Inputs waiting on people, each with answer()
agent.history(), historyPage({ before, limit })history(), history_page(...)The whole history, or a page of whole turns
agent.steer(text)steer()Join the running turn, or start one
agent.configure({ model, instructions, thinkingLevel, tools })configure(...)Change it between runs
agent.schedule({ text, inSeconds, at, everySeconds })schedule(...)Wake it later; schedules(), unschedule(id)
agent.filesagent.fileslist, download, upload, link by the paths the agent sees
agent.abort()abort()Stop the running turn
agent.delete()delete()Delete it, its history and files
agent.close()close()Close this process's connection

Run options for run and stream:

TypeScriptPython
useruser=Who sent it: your user id, or { id, name, username }
filesfiles=Attachments. See Files
metadatametadata=Your own key-value data (16 strings); the model never sees it
idempotencyKeyidempotency_key=The run's id. The same key returns the same run
signaltimeout=Stop waiting; the run goes on
throwOnErrorthrow_on_error=false returns a failed run instead of throwing RunError
whileRunningwhile_running="queue" (default) or "steer"
spendLimitspend_limit={usd}: this run's own budget
allowDisconnectedallow_disconnected=Run even with nobody serving the agent's tools

Run and stream parts

A Run is { id, status, text, inputs, error, usage, files, toolErrors, sourceErrors, raw }. status is completed, input_required or failed. Each of run.inputs has answer(value, { from }) and decline({ from }), which resolve with the resumed run.

Part typeFields
texttext: reply text as it's written
tool_callid, name, arguments
tool_resultid, name, output, isError
input_requiredinput, with answer()
donerun, always last

Tools

tool({ description, input: schema.Object({ ... }), execute: (args, context) => result,
       timeoutMs?, needsApproval?, exposure? })
context (TypeScript)Python
idempotencyKeyidempotency_keyThe same for every attempt of this call
callIdcall_idThis attempt's id
identityidentityWho the call is for. See Identity
signal(task cancellation)Aborted when camelRun cancels the call
progress(message)progress(message, progress=, total=)Report progress; restarts the deadline
confirm, ask, requireUrlconfirm, ask, require_urlAsk the user. See Human input

The lower-level API

Agents and Agent are built on AgentRuntime and AgentClient, which stay available for code that needs the wire's shape: agents.runtime, agent.client, or new AgentRuntime({ url, apiKey }) directly.

TypeScriptPython
runtime.upsertAgent(key, options)upsert_agent(key, ...)Upsert, returning credentials without connecting
runtime.connectAgent(session, { tools, attach, takeover })connect_agent(...)Connect with stored credentials
runtime.me()me()Your tenant id and default model
runtime.upsertDefinition(key, input)upsert_definition(key, ...)Definitions; also createDefinition, updateDefinition, deleteDefinition
runtime.setProvider(name, config)set_provider(name, ...)A custom provider
runtime.createVolume, volume(id)create_volume, volume(id)Volumes
runtime.inbox(state)inbox(state=)Inputs across all agents
client.execute(code)execute(code)Run code in the sandbox with the agent's tools, outside its history
client.waitForRequest(id)wait_for_request(id)Wait for a request already sent, from any process

Examples

Both examples read CAMELAI_API_KEY: