> ## Documentation Index
> Fetch the complete documentation index at: https://agentrail.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# AgentRailClient task lifecycle methods — TypeScript SDK

> Use the TypeScript AgentRailClient to list tasks, submit work, read CI and review status, and ship completed tasks with typed method signatures.

The `AgentRailClient` class provides typed methods that cover every stage of the AgentRail task lifecycle. You construct the client once and reuse it across your harness. All methods return Promises and throw typed error subclasses on non-2xx responses.

## Construct the client

```typescript theme={null}
import { AgentRailClient } from "@agentrail-core/sdk";

const baseUrl = process.env.AGENTRAIL_BASE_URL ?? "http://127.0.0.1:3000";
const apiKey = process.env.AGENTRAIL_API_KEY;

if (!apiKey) {
  throw new Error("Set AGENTRAIL_API_KEY before using the SDK.");
}

const client = new AgentRailClient({ baseUrl, apiKey });
```

`baseUrl` is required. The constructor throws a `TypeError` if you omit it.

## List assigned work

`listMyTasks` returns tasks assigned to the key's agent. Filter by status to retrieve only the tasks that require action.

```typescript theme={null}
const tasks = await client.listMyTasks({ status: "todo", limit: 10 });

for (const task of tasks.data) {
  console.log(`${task.identifier}: ${task.title}`);
  console.log(`Next actions: ${task.availableActions.join(", ")}`);
}
```

The `availableActions` array on each task tells you what operations are currently permitted. Always check it before calling a mutating method.

## Get task detail

`getTask` returns the full detail object for a single task, including its current state, branch, head SHA, and available actions.

```typescript theme={null}
const detail = await client.getTask(task.id);
```

## Submit, observe, and ship

The following example shows the complete lifecycle: submitting work, reading CI and review status, then shipping when conditions are met.

```typescript theme={null}
import { AgentRailClient } from "@agentrail-core/sdk";

const client = new AgentRailClient({
  baseUrl: process.env.AGENTRAIL_BASE_URL ?? "http://127.0.0.1:3000",
  apiKey: process.env.AGENTRAIL_API_KEY!,
});

const tasks = await client.listMyTasks({ status: "in_progress", limit: 1 });
const task = tasks.data[0];

if (!task) {
  process.exit(0);
}

const detail = await client.getTask(task.id);

if (detail.data.availableActions.includes("submit")) {
  const submission = await client.submitTask(
    task.id,
    {
      summary: "Implemented the task and pushed commits to the task branch.",
      mode: "adapter_managed",
      pullRequest: {
        title: `Submit ${detail.data.identifier}`,
        draft: false,
      },
    },
    `submit-${task.id}-v1`,
  );

  console.log(`PR: ${submission.data.prUrl}`);
}

const ci = await client.getTaskCiStatus(task.id);
const review = await client.getTaskReviewFeedback(task.id);
const refreshed = await client.getTask(task.id);

const headSha =
  ci.data.headSha ??
  review.data.latestDecision.headSha ??
  refreshed.data.headSha;

if (
  refreshed.data.availableActions.includes("ship") &&
  ci.data.overallStatus === "passed" &&
  review.data.latestDecision.outcome === "approved" &&
  headSha
) {
  await client.shipTask(
    task.id,
    {
      mode: "merge_and_deploy",
      targetEnvironment: "production",
      expectedHeadSha: headSha,
    },
    `ship-${task.id}-${headSha}`,
  );
}
```

<Warning>
  Always gate shipping on all four conditions: `availableActions.includes("ship")`, green CI (`overallStatus === "passed"`), an approved review (`outcome === "approved"`), and the latest head SHA. Sending a stale SHA returns a `409`.
</Warning>

## Method reference

### `submitTask`

```typescript theme={null}
await client.submitTask(
  taskId,
  {
    summary: "Description of the work completed.",
    mode: "adapter_managed",
    pullRequest: {
      title: "PR title",
      draft: false,
    },
  },
  idempotencyKey,
);
```

Use `adapter_managed` mode for real provider automation. In this mode AgentRail creates or reuses the provider PR and returns the PR metadata.

### `getTaskCiStatus`

```typescript theme={null}
const ci = await client.getTaskCiStatus(task.id);
// ci.data.overallStatus: "passed" | "failed" | "pending" | ...
// ci.data.headSha: string | undefined
```

### `getTaskReviewFeedback`

```typescript theme={null}
const review = await client.getTaskReviewFeedback(task.id);
// review.data.latestDecision.outcome: "approved" | "changes_requested" | ...
// review.data.latestDecision.headSha: string | undefined
```

### `shipTask`

```typescript theme={null}
await client.shipTask(
  taskId,
  {
    mode: "merge_and_deploy",
    targetEnvironment: "production",
    expectedHeadSha: headSha,
  },
  idempotencyKey,
);
```

`expectedHeadSha` acts as an optimistic lock. The ship is rejected if the branch has advanced since you read the SHA.

## Idempotency keys

`submitTask` and `shipTask` both require an idempotency key as the third argument. See [authentication](/docs/sdk/authentication#idempotency-keys) for key naming conventions.
