---
title: "SDK agent sessions"
canonical: https://trickest.com/docs/developer-tools/sdk/sessions
description: "Create agent sessions, follow state, run turns, and handle interrupts with @trickest/sdk."
---

# SDK agent sessions

Use **`client.sessions`** for agent conversations and tasks. A **`SessionHandle`** follows one conversation and sends turns. HTTP state projections supply the current state; WebSocket messages notify the client about changes and carry optional streaming deltas.

Examples use an authenticated server-side `client: TrickestClient`; session, vault, and workflow IDs are strings supplied by your application. Agent sessions are distinct from [sandbox execution sessions](/docs/developer-tools/sdk/sandbox).

## Create and manage sessions

| Method                                  | Result or purpose                                                                   |
| --------------------------------------- | ----------------------------------------------------------------------------------- |
| `list(vaultId, options?)`               | `Promise<Session[]>`; `pageSize` requests a limit, not an automatic pagination loop |
| `get(id, options?)`                     | Session metadata                                                                    |
| `create(vaultId, title?, options?)`     | Creates a session; options can include `workflowId`, `spaceId`, and `metadata`      |
| `archive(id, options?)`                 | Archives a session                                                                  |
| `delete(id, options?)`                  | Deletes a session                                                                   |
| `dispatch(params)`                      | Submits a turn and returns accepted run IDs                                         |
| `handle(sessionId, vaultId, options?)`  | Opens a state handle; `realtime` defaults to true                                   |
| `stop(sessionId, { runId? }, options?)` | Requests that the current agent run stop                                            |

```ts
const session = await client.sessions.create(vaultId, "Analysis", {
  workflowId,
});
const handle = await client.sessions.handle(session.id, vaultId, {
  realtime: true,
  messageLimit: 50,
});
try {
  const state = await handle.refresh();
  console.log(state.run.phase);
} finally {
  handle.close();
}
```

`close()` releases local subscriptions and the WebSocket connection. It does not stop a remote turn or delete the session. Use `abort()` or `client.sessions.stop()` when you intend to stop work.

## Follow state in an application

The function below returns cleanup for your application to call when its view closes. Keep the handle open while you need updates.

```ts
import type { TrickestClient } from "@trickest/sdk";

export async function observeSession(
  client: TrickestClient,
  sessionId: string,
  vaultId: string,
): Promise<() => void> {
  const handle = await client.sessions.handle(sessionId, vaultId);
  const unsubscribe = handle.subscribe((projection, change) => {
    console.log(projection.run.phase, change.sources);
  });
  try {
    await handle.refresh();
  } catch (error) {
    unsubscribe();
    handle.close();
    throw error;
  }
  return () => {
    unsubscribe();
    handle.close();
  };
}
```

For live text, use `subscribeStreaming()` and release its returned subscription when finished. State projections remain the source for the final result.

```ts
const unsubscribe = handle.subscribeStreaming((frame) => {
  if (frame.type === "text_stream_delta") process.stdout.write(frame.delta);
  if (frame.type === "text_stream_end") console.log(frame.finalStatus);
});
// Call unsubscribe() when the consuming view closes.
```

An explicit `wsUrl` on `TrickestClient`, or `TRICKEST_WS_URL`, overrides URL derivation. Remote origins normally use `/ws` with the matching ws/wss scheme. Supported local development ports map to the separate WebSocket server. Keep tokens server-side; do not expose this client in a browser component.

## Submit a turn

`send()` resolves when the server accepts a turn, with `{ runId, sessionId, jobId }`. It does not return the answer. Follow `subscribe()` updates or use `runTurn()` to wait.

| Option                  | Meaning                                                                            |
| ----------------------- | ---------------------------------------------------------------------------------- |
| `prompt`                | User request                                                                       |
| `agentMode`             | `agent` or `plan`; `ask` is not supported by this interface                        |
| `workflowId`, `spaceId` | Optional platform context                                                          |
| `editorMode`            | `workflow`, `app`, `agent`, or `database`                                          |
| `modelId`               | Model available to the account; omit to use the platform selection                 |
| `resume`                | Continue a paused turn without posting another user message                        |
| `autoApprove`           | Does not guarantee an interactive approval prompt; see the warning below |
| `signal`, `timeout`     | Control the dispatch HTTP request, not the lifetime of the remote agent run        |

## Wait for a result with `runTurn`

```ts
import { runTurn } from "@trickest/sdk";

const handle = await client.sessions.handle(sessionId, vaultId, {
  realtime: false,
});
try {
  const summary = await runTurn(
    handle,
    {
      prompt: "Summarize the findings in this session",
      agentMode: "agent",
    },
    { timeoutMs: 120_000 },
  );

  if (summary.success) {
    console.log(summary.answer);
    for (const call of summary.toolCalls) console.log(call.name, call.status);
  } else {
    console.error(summary.phase, summary.errorMessage);
  }
} finally {
  handle.close();
}
```

`runTurn()` polls for state by default, so it can work without WebSocket realtime. Do not run concurrent turns on the same handle. A successful summary means the turn completed without its recorded run error; inspect tool results before treating every underlying operation as successful.

The wait rejects on timeout; timeout and `close()` do not cancel the remote run.
If a turn pauses for input, your application must handle the interrupt or the
wait can expire.

<Warning>
  SDK-dispatched work can proceed without an interactive approval prompt, even
  with `autoApprove: false`. Obtain required approval before dispatching work;
  do not rely on this option to pause the agent. Platform permission restrictions
  still apply.
</Warning>

## Resolve interrupts deliberately

Read `getActiveInterrupt()` and obtain the user's decision before calling `resolveInterrupt()`. Decisions can concern permission, approval, plan approval, mode switching, or an answer to a question. The following function applies a permission decision already collected by your application:

```ts
import type { SessionHandle } from "@trickest/sdk";

export async function decidePermission(handle: SessionHandle, allow: boolean) {
  const interrupt = handle.getActiveInterrupt();
  if (interrupt?.type !== "permission") return;
  await handle.resolveInterrupt({
    type: "permission",
    id: interrupt.id,
    behavior: allow ? "allow" : "deny",
    rememberFor: "session",
  });
}
```

`inject(content)` sends additional input to an active turn. If it returns `injected: false`, submit a new turn with `send()` when appropriate.

## Tasks and field compatibility

`listTasks(vaultId)` returns a promise of tasks. `createTask(data)`, `updateTask(id, data)`, and `deleteTask(id)` manage them. Use `description` for the body.

The task types differ from platform validation for fields such as priority, due dates, and status. Use a minimal creation payload and check the API contract before passing those fields:

```ts
const task = await client.sessions.createTask({
  vaultId,
  title: "Review the analysis output",
  description: "Check the generated report against the source files.",
  sessionId,
});
console.log(task.id);
```

## Related

- [Memory & skills](/docs/developer-tools/sdk/memory-skills): durable context and installed instructions.
- [Agent integrations](/docs/developer-tools/sdk/agent-integrations): choose the appropriate client surface.
- [CLI sessions](/docs/developer-tools/cli/sessions-skills): command-line conversation operations.

---
_Markdown source of https://trickest.com/docs/developer-tools/sdk/sessions._
