---
url: https://salimhamed.github.io/jigs/api/factory/routines.md
---
# factory/routines

Workflow operations bound to your factory's durable step wrappers, imported from
`#jigs/routines`. Routines compose recorded steps and waits; they have no recorded result of
their own.

## Agents and models

### agentSession() {#agentsession-1}

```ts
const agentSession: (options) => AgentSession;
```

One agent across several turns: resumes the session it holds, or starts fresh when it cannot.

#### Parameters

| Parameter | Type | Description |
| :------ | :------ | :------ |
| `options` | { `cwd`: `string`; `harness`: [`Harness`](../jigs.md#harness-3); `name`: `string`; } | - |
| `options.cwd` | `string` | - |
| `options.harness` | [`Harness`](../jigs.md#harness-3) | - |
| `options.name` | `string` | Names the session in log lines. |

#### Returns

[`AgentSession`](#agentsession)

#### Remarks

Each turn supplies an incremental `resume` prompt and a complete `fresh` prompt.
A prompt may be a function, evaluated only when selected. A missing session or
changed harness descriptor starts fresh. The helper is rebuilt on replay;
recorded `AgentSessionRef` data restores the session reference.

***

### askAgent() {#askagent}

```ts
const askAgent: <T>(config) => Promise<AgentResult<T>> = agents.askAgent;
```

Ask an agent harness without tools or a worktree.

#### Type Parameters

| Type Parameter | Default type |
| :------ | :------ |
| `T` | `undefined` |

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `config` | [`AskAgentOptions`](../jigs.md#askagentoptions)<`T`> |

#### Returns

`Promise`<[`AgentResult`](../jigs.md#agentresult)<`T`>>

***

### askJev() {#askjev}

```ts
const askJev: <QUESTIONS>(config) => Promise<JevResult<QUESTIONS>> = agents.askJev;
```

Ask a decision model named questions and receive calibrated typed answers.

#### Type Parameters

| Type Parameter |
| :------ |
| `QUESTIONS` *extends* [`JevQuestions`](../jigs.md#jevquestions) |

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `config` | [`AskJevOptions`](../jigs.md#askjevoptions)<`QUESTIONS`> |

#### Returns

`Promise`<[`JevResult`](../jigs.md#jevresult)<`QUESTIONS`>>

***

### askModel() {#askmodel}

```ts
const askModel: <T>(config) => Promise<ModelResult<T>> = agents.askModel;
```

Ask a model without tools and validate its answer against your output schema.

#### Type Parameters

| Type Parameter | Default type |
| :------ | :------ |
| `T` | `undefined` |

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `config` | [`AskModelOptions`](../jigs.md#askmodeloptions)<`T`> |

#### Returns

`Promise`<[`ModelResult`](../jigs.md#modelresult)<`T`>>

***

### runAgent() {#runagent}

```ts
const runAgent: <T>(config) => Promise<AgentResult<T>> = agents.runAgent;
```

Run an agent with tools and validate its answer against your output schema.

#### Type Parameters

| Type Parameter | Default type |
| :------ | :------ |
| `T` | `undefined` |

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `config` | [`RunAgentOptions`](../jigs.md#runagentoptions)<`T`> |

#### Returns

`Promise`<[`AgentResult`](../jigs.md#agentresult)<`T`>>

## Agent and model requests/results

### AgentSession {#agentsession}

One agent across several turns of a workflow.

#### Remarks

`run` resumes the harness session the agent session holds. When that session is gone, or it was
recorded on a different harness descriptor, `run` starts fresh with the `fresh` prompt instead.

#### Methods

##### run() {#run}

###### Call Signature

```ts
run<T>(turn): Promise<T>;
```

With `output`, the answer is validated against it and returned parsed. An invalid answer is
asked for once more with the reasons, as `runAgent` does, and never sends the turn back to
`fresh`; a second invalid answer throws its `ZodError`.

###### Type Parameters

| Type Parameter |
| :------ |
| `T` |

###### Parameters

| Parameter | Type |
| :------ | :------ |
| `turn` | [`AgentSessionTurn`](#agentsessionturn) & `object` |

###### Returns

`Promise`<`T`>

###### Call Signature

```ts
run(turn): Promise<void>;
```

###### Parameters

| Parameter | Type |
| :------ | :------ |
| `turn` | [`AgentSessionTurn`](#agentsessionturn) |

###### Returns

`Promise`<`void`>

#### Properties

| Property | Type |
| :------ | :------ |
|  `harness` | [`Harness`](../jigs.md#harness-3) |

***

### AgentSessionTurn {#agentsessionturn}

The two ways to state one turn of an agent session.

#### Properties

| Property | Type | Description |
| :------ | :------ | :------ |
|  `fresh` | `string` | () => `Promise`<`string`> | Sent to an agent starting from nothing: everything it needs. A function is called only when the session starts fresh, so gathering its context costs nothing on a resume. |
|  `resume` | `string` | () => `Promise`<`string`> | Sent to an agent that already holds the earlier turns: only what is new. A function is called only when the resume is taken. |

## Linear and human input

### haltForHuman() {#haltforhuman}

```ts
const haltForHuman: (claim, halt) => Promise<HumanReply> = linear.haltForHuman;
```

Ask in the ticket's Linear agent session and wait for a reply there.

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `claim` | [`TicketClaim`](../jigs.md#ticketclaim) |
| `halt` | [`Halt`](../jigs.md#halt) |

#### Returns

`Promise`<[`HumanReply`](../jigs.md#humanreply)>

#### Remarks

Posts the question in the session the claim holds, then waits until someone
answers in it. Messages sent there since the run last read it answer at once.
The question mentions the operator (or the ticket's creator) and the assignee;
list more emails in the halt's `mention`.

***

### noteOnTicket() {#noteonticket}

```ts
const noteOnTicket: (claim, note) => Promise<void> = linear.noteOnTicket;
```

Post a note in the ticket's Linear agent session that asks for nothing and waits for nothing.
Set `run: "ended"` on the run's last note, success or not, to end the session. Set
`run: "waiting"` before a long wait on people, so the session shows awaiting input and never
goes stale.

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `claim` | [`TicketClaim`](../jigs.md#ticketclaim) |
| `note` | [`TicketNote`](../jigs.md#ticketnote) |

#### Returns

`Promise`<`void`>

***

### acquireTicket() {#acquireticket}

```ts
function acquireTicket(ticket): Promise<{
  claim: TicketClaim;
  snapshot: TicketSnapshot;
}>;
```

Resolve a Linear ticket in the named Linear installation, claim it, and read its requirements,
before any protected work. The run opens a Linear agent session on the ticket, or takes the
`session` that started it, and talks to people only there.

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `ticket` | { `installationName`: `string`; `reference`: `string`; `session?`: `string`; } |
| `ticket.installationName` | `string` |
| `ticket.reference` | `string` |
| `ticket.session?` | `string` |

#### Returns

`Promise`<{
`claim`: [`TicketClaim`](../jigs.md#ticketclaim);
`snapshot`: [`TicketSnapshot`](../jigs.md#ticketsnapshot);
}>

## Pull requests

### postPullRequestNote() {#postpullrequestnote}

```ts
const postPullRequestNote: (options) => Promise<void> = pullRequests.postPullRequestNote;
```

Post a note about a commit, once per head and reason.

#### Parameters

| Parameter | Type | Description |
| :------ | :------ | :------ |
| `options` | { `body`: `string`; `headSha`: `string`; `pr`: [`PullRequestRef`](../jigs.md#pullrequestref); `reason`: [`StatusReason`](../jigs.md#statusreason); `scope`: `string`; } | - |
| `options.body` | `string` | The Markdown note body. |
| `options.headSha` | `string` | The commit the note is about: a red head, or a head it could not merge. |
| `options.pr` | [`PullRequestRef`](../jigs.md#pullrequestref) | The pull request receiving the note. |
| `options.reason` | [`StatusReason`](../jigs.md#statusreason) | Labels the update so CI and merge notes for the same commit stay independent. |
| `options.scope` | `string` | The continuation identity that owns the note. |

#### Returns

`Promise`<`void`>

#### Remarks

Reads current comments and skips a note already marked with this scope, head and reason.
Use `ci` for a CI update, `merge` for a merge refusal, or `merge-retry` for a temporary
refusal. The reason does not change readiness or schedule more work. Posting failures
are logged and return without throwing; the workflow decides whether to try again.

***

### watchPullRequest() {#watchpullrequest}

```ts
const watchPullRequest: (pr, options?) => AsyncGenerator<PullRequestSnapshot, void, undefined> = pullRequests.watchPullRequest;
```

Read current pull request facts, then yield changed snapshots until it closes.

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `pr` | [`PullRequestRef`](../jigs.md#pullrequestref) |
| `options?` | [`PullRequestReadOptions`](../jigs.md#pullrequestreadoptions) |

#### Returns

`AsyncGenerator`<[`PullRequestSnapshot`](../jigs.md#pullrequestsnapshot), `void`, `undefined`>

#### Remarks

Reads once immediately, then rereads on each GitHub event from the hub and on `jigs poke`.
Duplicate wakes and reordered collections with unchanged facts do not yield again.
Snapshots include comments regardless of author or jigs markers; the workflow
owns decisions, action limits and merging. A closed snapshot is yielded once.
Leaving the loop releases the watch. Only one run may watch a pull request;
a second owner receives `ClaimConflictError`.

## Pull request delivery

### buildAndReview() {#buildandreview}

```ts
const buildAndReview: <W>(delivery, options) => Promise<BuildResult> = delivery.buildAndReview;
```

Build and review a delivery's change until the reviewer raises no blocking finding.
Ends `approved` with the reviewed commit, or `stopped` when the rounds run out or there is
nothing to review.

#### Type Parameters

| Type Parameter |
| :------ |
| `W` |

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `delivery` | [`BuildDelivery`](../jigs.md#builddelivery)<`W`> |
| `options` | [`BuildAndReviewOptions`](../jigs.md#buildandreviewoptions) |

#### Returns

`Promise`<[`BuildResult`](../jigs.md#buildresult)>

***

### describePullRequest() {#describepullrequest}

```ts
const describePullRequest: <W>(delivery, options) => Promise<Described> = delivery.describePullRequest;
```

Have the writer, or the builder, write the pull request's title and body from the diff.
An optional `check` returns problems; the writer is sent back once with them.

#### Type Parameters

| Type Parameter |
| :------ |
| `W` |

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `delivery` | [`DescribeDelivery`](../jigs.md#describedelivery)<`W`> |
| `options` | [`DescribeOptions`](../jigs.md#describeoptions) |

#### Returns

`Promise`<[`Described`](../jigs.md#described)>

***

### followPullRequestToOutcome() {#followpullrequesttooutcome}

```ts
const followPullRequestToOutcome: <W>(delivery, pr, options) => Promise<FollowResult> = delivery.followPullRequestToOutcome;
```

Follow a delivery's pull request until it merges or closes, waking the builder for feedback.
Ends `merged` or `closed`.

#### Type Parameters

| Type Parameter |
| :------ |
| `W` |

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `delivery` | [`FollowDelivery`](../jigs.md#followdelivery)<`W`> |
| `pr` | [`PullRequestRef`](../jigs.md#pullrequestref) |
| `options` | [`FollowOptions`](../jigs.md#followoptions) |

#### Returns

`Promise`<[`FollowResult`](../jigs.md#followresult)>

#### Remarks

`wake` decides what wakes the builder; pass `builderWakeFacts` for the default rules. A pull
request that needs a person, a blocked merge included, reaches the workflow through
`onNeedsHuman` with facts; the workflow words and sends any note. When `mergeWhen` agrees, an
approved, green, clean pull request merges once local work is published.

***

### publishPullRequest() {#publishpullrequest}

```ts
const publishPullRequest: (delivery, options) => Promise<RepositoryRef & object & object> = delivery.publishPullRequest;
```

Push exactly the given commit and open its pull request with the given title and body.

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `delivery` | [`PublishDelivery`](../jigs.md#publishdelivery) |
| `options` | [`PublishOptions`](../jigs.md#publishoptions) |

#### Returns

`Promise`<[`RepositoryRef`](../jigs.md#repositoryref) & `object` & `object`>

## Slack messages

### waitForSlackReply() {#waitforslackreply}

```ts
function waitForSlackReply(question): Promise<SlackReplyResult>;
```

Wait for a human reply in a Slack thread after `lastRead`. Ends `replied` with every such
reply, never empty and oldest first, `timed-out` after `until`, or `gone` if deleted.

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `question` | [`SlackQuestion`](../jigs.md#slackquestion) |

#### Returns

`Promise`<[`SlackReplyResult`](../jigs.md#slackreplyresult)>

#### Remarks

Binds the library's `waitForSlackReply` routine to this factory's `fetchSlackMessage`
step; its documentation covers deadlines, wakes, deletion and conflicts.

## Git changes

### committedWork() {#committedwork}

```ts
committedWork: (worktree, options?) => Promise<{
  commits: number;
  dirty: boolean;
  headSha: string;
}>;
```

Read branch state, failing unless there is a new commit and no uncommitted work.

#### Parameters

| Parameter | Type | Description |
| :------ | :------ | :------ |
| `worktree` | [`Worktree`](../jigs.md#worktree-3) | - |
| `options?` | { `since?`: `string`; } | - |
| `options.since?` | `string` | A commit SHA to count new commits from. Defaults to the worktree's base commit. |

#### Returns

`Promise`<{
`commits`: `number`;
`dirty`: `boolean`;
`headSha`: `string`;
}>

#### Remarks

Counts commits since the worktree base, or `options.since` when supplied.
Returns the head SHA, commit count and clean state; fails with a repair hint
if the agent left no new commit or uncommitted changes.

## Linear agent sessions

### linearAgentConversation() {#linearagentconversation}

```ts
function linearAgentConversation(session, options): Promise<LinearAgentConversationResult>;
```

Hold a conversation with Claude in the Linear agent session that started this run, until no
one replies for `idleFor` (four hours by default), someone presses stop, or a turn fails.

#### Parameters

| Parameter | Type |
| :------ | :------ |
| `session` | | [`LinearDelegationInputs`](../jigs.md#lineardelegationinputs) | [`LinearMentionInputs`](../jigs.md#linearmentioninputs) |
| `options` | [`LinearAgentConversationOptions`](../jigs.md#linearagentconversationoptions) |

#### Returns

`Promise`<[`LinearAgentConversationResult`](../jigs.md#linearagentconversationresult)>

#### Remarks

Binds the library's `linearAgentConversation` routine to this factory's steps; its
documentation covers turns, stops and what Linear shows.
