Orcha
How to use durable sessions

Resume a session

Resume an OrchaJS session with .resume(), including human-in-the-loop client actions.

Use .resume() with a saved sessionId to continue the same conversation:

const result = await orcha.supportAgent.resume(sessionId, {
  content: "What should I do next?",
}).result;

Orcha loads the durable context automatically. Do not send previous messages again.

Run, resolve a client action, and resume

A client action moves work into your application. The following is the entire flow in one place:

// 1. Start the session.
let result = await orcha.approvalAgent.run({
  content: "Approve a $750 laptop.",
  clientCapabilities: ["request_human_approval"],
}).result;

// 2. The agent paused and requested work from your client.
if (result.status === "waiting_for_client_action") {
  const call = result.clientToolCalls[0];

  if (call.name === "request_human_approval") {
    // Resolve this in your UI, mobile app, worker, or other client.
    const approved = await showApprovalDialog(call.arguments);

    // 3. Return the result and continue the same run.
    result = await orcha.approvalAgent.resume(result.sessionId, {
      toolResults: [
        {
          callId: call.callId,
          output: {
            approved,
            note: "Decision submitted by the user.",
          },
        },
      ],
    }).result;
  }
}

if (result.status === "completed") {
  console.log(result.output);
}

Use call.name to identify the requested client action. call.arguments matches that action's parameters; the returned output must match its outputSchema.

For example, a location action can return the fields defined by its own schema:

{
  callId: call.callId,
  output: {
    latitude: 28.6139,
    longitude: 77.209,
  },
}

Resolve multiple client actions

Return one result for every requested call in one .resume():

if (result.status === "waiting_for_client_action") {
  const toolResults = await Promise.all(
    result.clientToolCalls.map(async (call) => {
      const output = await handleClientAction(call.name, call.arguments);

      return {
        callId: call.callId,
        output,
      };
    }),
  );

  const next = await orcha.supportAgent.resume(result.sessionId, {
    toolResults,
  }).result;
}

Every pending callId must appear exactly once.

When a client action fails

Keep normal results simple. Add isError: true only when your client could not perform the action:

{
  callId: call.callId,
  output: {
    message: "The user denied location access.",
  },
  isError: true,
}

The agent receives that failure and can decide what to do next.

API reference

Continue the conversation

resume(
  sessionId: string,
  input?: string | {
    content: string | MessageContent | MessageContent[];
    clientCapabilities?: Array<string | { name: string }>;
  },
): Execution
  • sessionId — the existing session to continue.
  • content — the next user message.
  • clientCapabilities — client actions available for this resumed run.
  • Omitting input asks the agent to "Continue.".

A conversational resume starts a new numbered run in the same session.

Resolve pending client actions

resume(
  sessionId: string,
  input: {
    toolResults: Array<{
      callId: string;
      output: ClientActionOutput;
      isError?: boolean;
    }>;
  },
): Execution
  • callId — copy it unchanged from the requested call.
  • output — data matching that client action's outputSchema.
  • isError — optional; use true only when the client action failed.

Do not combine content and toolResults. While actions are pending, resolve them before sending another conversational message.

Requested call

type ClientToolCall = {
  callId: string;
  name: string;
  arguments: Record<string, unknown>;
};
  • callId uniquely pairs the request with its result.
  • name is the client action name from its index.json.
  • arguments matches the action's parameters schema.

Result

.resume() returns the same Execution and RunResult shapes as run():

  • completed — read result.output.
  • waiting_for_client_action — resolve the new clientToolCalls.
  • paused — the session was explicitly paused.
  • failed — inspect result.error.

Common client-action errors include missing results, an unknown or duplicated callId, output that does not match the action schema, and trying to send content while actions remain pending.