Runtime methods

What each method of the runtime does, with every input and result.

createRuntime returns the runtime. Your server calls it from its routes: one call per chat message, approval decision or cron tick. Every method that takes a principal only ever sees that principal's data.

OptionTypeDefaultDetails
listAgents(principal: P) => Promise<AgentInfo[]>—
handleChat(input: HandleChatInput<P>) => Promise<Response>—
runAgent(input: RunAgentInput<P>) => Promise<RunAgentResult>—
compactChatfunction—
loadHistoryfunction—
listChatsfunction—
getChatfunction—
listRunsfunction—
getRunfunction—
deleteChatfunction—
purgeOwnerfunction—
resumefunction—
sweepfunction—
cronfunction—
applyApproval(input: ApplyApprovalInput<P>) => Promise<Response>—
applyToolResult(input: ApplyToolResultInput<P>) => Promise<Response>—
schedule(input: ScheduleInput<P>) => Promise<ScheduleRecord>—
listSchedulesfunction—
unschedulefunction—
runScheduleNowfunction—
runDuefunction—

handleChat

Runs one chat turn and streams the answer back. Return its Response straight from your route to useChat.

ts
export async function POST(req: Request) {
  const principal = await requireUser(req);
  const { id, message, agent } = await req.json();
  return runtime.handleChat({ agent, chatId: id, principal, message, request: req });
}
OptionTypeDefaultDetails
agent?string—
chatId?string—
principalP—
messageAppMessage—
params?unknown—
request?Request—
turnContext?unknown—

runAgent

Runs an agent to completion with no client attached: a webhook, a background job, a test. Returns the final answer.

ts
const { answer, error } = await runtime.runAgent({
  principal,
  agent: "triage",
  prompt: `New ticket: ${ticket.title}`,
  trigger: "programmatic",
});
OptionTypeDefaultDetails
principalP—
agentstring—
promptstring—
files?array—
threadId?string—
params?unknown—
blockGated?"simulate-success" | booleantrue
memory?boolean—
model?LanguageModel—
turnContext?unknown—
promptCaching?boolean—
trigger?TurnTrigger"programmatic"

It returns:

OptionTypeDefaultDetails
threadIdstring—
answerstring—
error?string—

applyApproval

Continues a run that paused on a tool needing approval. Decisions that are no longer pending (a double click, an old tab) are ignored, so it is safe to call more than once.

ts
return runtime.applyApproval({
  chatId,
  principal,
  decisions: [{ approvalId, approved: true }],
});
OptionTypeDefaultDetails
chatIdstring—
principalP—
decisionsApprovalDecision[]—
request?Request—
turnContext?unknown—

Each decision:

OptionTypeDefaultDetails
approvalIdstring—
approvedboolean—
reason?string—

applyToolResult

Continues a run that paused on a tool the client answers, such as askUser.

OptionTypeDefaultDetails
chatIdstring—
principalP—
toolCallIdstring—
outputunknown—
request?Request—
turnContext?unknown—

schedule

Runs an agent on a timer, as the caller. Recurring schedules need cron in the runtime config, and a timer calling runtime.cron().

ts
await runtime.schedule({
  principal,
  agent: "brief",
  cron: "0 9 * * 1",
  timezone: "Europe/Helsinki",
  prompt: "Summarise last week's tickets.",
});
OptionTypeDefaultDetails
principalP—
agentstring—
cronstring | null—
timezone?string"UTC"
promptstring—
delivery?unknown—
onParked?"fire" | "skip""skip"
params?unknown—

cron

The one function to call on a timer, every minute or so. It fires due schedules and, with durability on, resumes interrupted runs. Safe to call from every server at once.

ts
// app/api/cron/route.ts — called by your platform's cron every minute
export async function GET() {
  const { due, resumed, errors } = await runtime.cron();
  return Response.json({ fired: due.fired, resumed: resumed.length, errors });
}

What due reports:

OptionTypeDefaultDetails
firednumber—
errorsnumber—
skippednumber—
parkednumber—
rejectednumber—