Reconnecting to Existing Coder Sessions — Agentuity Documentation

Reconnecting to Existing Coder Sessions

Use listConnectableSessions and prepareSessionForRemoteAttach to find sessions you can still reconnect to

For a "resume session" or "attach to session" flow, don't start from the full session list. Use listConnectableSessions() to narrow the choices, then prepareSessionForRemoteAttach() to decide whether the selected session is live, wakeable, or already history-only.

The Pattern

Listing Reconnectable Sessions

Use listConnectableSessions() when you want to show only sessions that still have a reconnect story.

import { CoderClient } from '@agentuity/coder';
 
async function main(): Promise<void> {
  const client = new CoderClient();
 
  try {
    // listConnectableSessions filters out history-only sessions so your picker starts from resumable candidates
    const { sessions } = await client.listConnectableSessions({ limit: 20 }); 
 
    console.log(
      JSON.stringify(
        sessions.map((session) => ({
          sessionId: session.sessionId,
          label: session.label,
          status: session.status,
          bucket: session.bucket,
          runtimeAvailable: session.runtimeAvailable,
          wakeAvailable: session.wakeAvailable,
        })),
        null,
        2
      )
    );
  } catch (error) {
    const message = error instanceof Error ? error.stack ?? error.message : String(error);
    console.error('Failed to list reconnectable sessions');
    console.error(message);
    process.exitCode = 1;
  }
}
 
void main();

An empty list is common. Sessions in bucket: 'provisioning' are intentionally excluded until they reach running or paused, so a session you just created won't show up yet. Others may be absent because they're already history-only or no longer in a resumable state.

Preparing One Session for Reconnect

Once a user picks a session, use prepareSessionForRemoteAttach() to check whether it is live, wakeable, or already read-only.

import { CoderClient } from '@agentuity/coder';
 
const sessionId = process.argv[2];
 
async function main(): Promise<void> {
  const client = new CoderClient();
 
  try {
    if (!sessionId) {
      throw new Error(
        'Pass a session ID as the first argument, for example: bun example.ts codesess_123'
      );
    }
 
    // Polls until the session is attachable, wakeable, or history-only
    // The returned session carries the live flags your UI branches on below
    const session = await client.prepareSessionForRemoteAttach(sessionId, { 
      timeoutMs: 30_000,
      pollIntervalMs: 1_000,
    });
 
    if (session.historyOnly) {
      // The live runtime is gone. Hydrate from replay or a read-only view instead
      console.log('Session is history-only. Use replay or session detail instead of re-attaching.');
      return;
    }
 
    if (session.runtimeAvailable) {
      // Attaching before the runtime is up fails; this check confirms it's ready
      console.log('Session is attachable.');
      console.log(
        JSON.stringify(
          {
            sessionId: session.sessionId,
            status: session.status,
            bucket: session.bucket,
            runtimeAvailable: session.runtimeAvailable,
          },
          null,
          2
        )
      );
      return;
    }
 
    // wakeAvailable is false, so prepareSessionForRemoteAttach returned immediately
    // without polling. Typical for provisioning-bucket sessions that aren't yet wakeable
    console.log('Session is not attachable yet.');
    console.log(
      JSON.stringify(
        {
          sessionId: session.sessionId,
          status: session.status,
          bucket: session.bucket,
          runtimeAvailable: session.runtimeAvailable,
          wakeAvailable: session.wakeAvailable,
          historyOnly: session.historyOnly,
        },
        null,
        2
      )
    );
  } catch (error) {
    const message = error instanceof Error ? error.stack ?? error.message : String(error);
    console.error('Failed to prepare the session for remote attach');
    console.error(message);
    process.exitCode = 1;
  }
}
 
void main();

What to Look For

The two methods solve different parts of the reconnect story:

  • listConnectableSessions() builds a clean picker or "resume recent work" list
  • prepareSessionForRemoteAttach() runs the state check for one chosen session
  • runtimeAvailable: true means the runtime is ready for a controller client
  • historyOnly: true means the live runtime is gone, so fall back to the replay hydration stream or listEventHistory()
  • wakeAvailable: true means the session may be resumable, even if it isn't live yet

Use listConnectableSessions() instead of listSessions() here. It already filters out history-only sessions, so your UI starts from sessions that still have a reconnect path.

In app code, call prepareSessionForRemoteAttach() right before your app opens a live connection to the session, whether that's to send messages to the agent or stream its events. It returns the current session detail so your app can branch on runtimeAvailable, wakeAvailable, and historyOnly. A thrown error usually means the underlying getSession() or resumeSession() call failed, so handle it like any other SDK error.

Example Output

An attachable session may look like this:

{
  "sessionId": "codesess_abc123",
  "status": "active",
  "bucket": "running",
  "runtimeAvailable": true
}

A session that can no longer be re-attached falls back to session history or stored session data instead:

{
  "sessionId": "codesess_def456",
  "status": "archived",
  "bucket": "history",
  "runtimeAvailable": false,
  "wakeAvailable": false,
  "historyOnly": true
}

Key Points

  • Use listConnectableSessions() for chooser UIs, resume commands, and recent-session pickers.
  • Call prepareSessionForRemoteAttach() right before your app opens its live connection to the session, and branch on runtimeAvailable, wakeAvailable, and historyOnly to decide the next step.
  • If the timeout expires, you still get the latest session detail, which is useful for your own retry logic.
  • Once a session is historyOnly, switch to the replay hydration stream or listEventHistory() for a structured timeline.
  • For the CLI flow, agentuity coder tui --remote builds on the same reconnect idea.

See Also