Skip to content

steps ​

Build a factory's own agent step. createAgentRunner opens a harness the way the built-in agent step does and hands back the live provider model.

Call these inside a factory-owned "use step" function, never from a workflow. Driver, DriverContext, AgentRunner and the types they reach are a published contract: a change to any of them is a breaking release.

Classes ​

AgentSessionError ​

A durable agent session is missing or cannot be resumed by this harness.

Extends ​

  • Error

Properties ​

PropertyTypeDefault value
name"AgentSessionError""AgentSessionError"

Interfaces ​

AgentRunner ​

A harness ready to run in a worktree, from createAgentRunner. Pass model to the AI SDK's generateText, read the session reference from its result with sessionFrom, and call close when the call is done.

Properties ​

PropertyTypeDescription
modelLanguageModelThe live provider model, with jigs' policy already applied.

Methods ​

close() ​
ts
close(): Promise<void>;

Release the worktree lock and stop what the harness started. Safe to call twice.

Returns ​

Promise<void>

sessionFrom() ​
ts
sessionFrom(result): AgentSessionRef | undefined;

The session reference in a generateText result, for a later step to resume.

Parameters ​
ParameterType
result{ providerMetadata?: Record<string, Record<string, unknown>> | null; }
result.providerMetadata?Record<string, Record<string, unknown>> | null
Returns ​

AgentSessionRef | undefined


AgentRunnerOptions ​

Where createAgentRunner runs a harness, and the session it resumes.

Properties ​

PropertyTypeDescription
cwdstringThe worktree the agent works in.
resume?AgentSessionRefA session reference from an earlier call to resume.
runRunMetadataThe run the step belongs to: getWorkflowMetadata() inside the step.

Check ​

One requirement check with a stable id and a label for reports.

Properties ​

PropertyType
idstring
labelstring

Methods ​

run() ​
ts
run(): Promise<CheckResult>;
Returns ​

Promise<CheckResult>


Driver ​

How jigs runs one harness or model-source kind: its checks, the environment it may see, and how it asks, runs or opens a provider model. Each kind a descriptor can name has exactly one driver inside jigs; a factory cannot register another.

Remarks ​

A factory reads this to know what createAgentRunner does before it hands back a model. The shape is a published contract: changing it is a breaking release.

Type Parameters ​

Type Parameter
K extends HarnessKind | ModelKind

Properties ​

PropertyTypeDescription
displayNamestring-
familyK extends "claude" | "codex" | "pi" ? "harness" : "model"-
kindK-
minimumVersion?string-
sessionPointer?object-
sessionPointer.fieldstring-
sessionPointer.providerKeystring-
setsEnvreadonly string[]Names the driver sets in the harness environment itself, such as a private home.

Methods ​

ask()? ​
ts
optional ask(request, context): Promise<ExecutorGeneration>;
Parameters ​
ParameterType
request| AgentRequest | ModelRequest
contextDriverContext
Returns ​

Promise<ExecutorGeneration>

decide()? ​
ts
optional decide<QUESTIONS>(request, context): Promise<DecisionGeneration<QUESTIONS>>;
Type Parameters ​
Type Parameter
QUESTIONS extends JevQuestions
Parameters ​
ParameterType
requestAskJevOptions<QUESTIONS>
contextDriverContext
Returns ​

Promise<DecisionGeneration<QUESTIONS>>

descriptorChecks()? ​
ts
optional descriptorChecks(source): Check[];
Parameters ​
ParameterType
source| Extract<OpenrouterSource, { kind: K; }> | Extract<OpenaiCompatibleSource, { kind: K; }> | Extract<OpenaiCodexSource, { kind: K; }>
Returns ​

Check[]

envAllowlist() ​
ts
envAllowlist(request): readonly string[];
Parameters ​
ParameterType
requestDriverRequest
Returns ​

readonly string[]

installationChecks() ​
ts
installationChecks(): Check[];
Returns ​

Check[]

jitChecks()? ​
ts
optional jitChecks(target): Check[];
Parameters ​
ParameterType
targetHarnessTarget
Returns ​

Check[]

open()? ​
ts
optional open(target, context): Promise<OpenedModel>;

Build the live provider model for a run. Drivers without a provider model implement run.

Parameters ​
ParameterType
targetHarnessTarget
contextOpenContext
Returns ​

Promise<OpenedModel>

requestChecks() ​
ts
requestChecks(request): Check[];
Parameters ​
ParameterType
requestDriverRequest
Returns ​

Check[]

resolveExecutable()? ​
ts
optional resolveExecutable(env): string;
Parameters ​
ParameterType
envProcessEnv
Returns ​

string

run()? ​
ts
optional run(request, context): Promise<ExecutorGeneration>;
Parameters ​
ParameterType
requestOmit<RunAgentOptions<undefined>, "output"> & object
contextDriverContext
Returns ​

Promise<ExecutorGeneration>


DriverContext ​

What a driver receives for one call: the run it belongs to, the harness environment jigs built for it, and, for a structured call, the output spec a provider model consumes. deps is jigs' own wiring, not part of the contract.

Properties ​

PropertyType
envRecord<string, string>
metadataRunMetadata
output?Output<unknown, unknown, never>

OpenContext ​

What a driver's open receives: the run and the harness environment jigs built.

Properties ​

PropertyType
envRecord<string, string>
metadataRunMetadata

OpenedModel ​

A live provider model and what closing it releases.

Properties ​

PropertyType
modelLanguageModel

Methods ​

close() ​
ts
close(): Promise<void>;
Returns ​

Promise<void>

Type Aliases ​

CheckResult ​

ts
type CheckResult = 
  | {
  detail?: string;
  ok: true;
}
  | {
  ok: false;
  reason: string;
  repair: string;
};

A check's outcome: a pass with an optional detail, or a failure with its repair.


DecisionGeneration ​

ts
type DecisionGeneration<QUESTIONS> = object;

What a driver's decide returns: one answer per question.

Type Parameters ​

Type ParameterDefault type
QUESTIONS extends JevQuestionsJevQuestions

Properties ​

PropertyType
answersJevAnswers<QUESTIONS>

DriverRequest ​

ts
type DriverRequest = 
  | AgentRequest
  | ModelRequest
  | AskJevOptions<JevQuestions>
  | HarnessTarget;

Any request a driver's checks and environment allowlist are asked about.


ExecutorGeneration ​

ts
type ExecutorGeneration = ModelGeneration & object;

What a driver's call returns: the reply text, provider metadata and any structured output.

Type Declaration ​

NameType
output?unknown

HarnessTarget ​

ts
type HarnessTarget = object;

A harness to open in a worktree, resuming a session when one is given.

Properties ​

PropertyType
cwdstring
harnessHarness
resume?AgentSessionRef

RunMetadata ​

ts
type RunMetadata = Pick<WorkflowMetadata, "workflowRunId">;

The run a step belongs to: getWorkflowMetadata() inside the step.


RunRequest ​

ts
type RunRequest = Extract<AgentRequest, {
  cwd: string;
}>;

An agent request that runs in a worktree.

Functions ​

createAgentRunner() ​

ts
function createAgentRunner(harness, options): Promise<AgentRunner>;

Open a Claude Code or Codex harness inside a factory's own step, the way the built-in agent step does: the environment allowlist with the factory's agents.env, the request and just-in-time checks, the worktree lock, Codex's private home and app server, and the Claude spawn hook. The returned model is the live provider, ready for generateText.

Parameters ​

ParameterType
harnessHarness
optionsAgentRunnerOptions

Returns ​

Promise<AgentRunner>

Remarks ​

Call it inside a "use step" function, never in a workflow. The step can hand the provider a function, such as a tool-approval hook or a logger, because a step runs where functions are allowed; pass it through the AI SDK call.

It throws JitCheckError when a just-in-time check fails, and AgentSessionError when resume names a session this harness cannot resume. Pi has no provider model, so a Pi descriptor throws: run Pi with runAgent.

Example ​

ts
import type { AgentSessionRef, Harness } from "@jigs-ai/jigs";
import { createAgentRunner } from "@jigs-ai/jigs/steps";
import { generateText } from "ai";
import { getWorkflowMetadata } from "workflow";

export async function runWithTemperature(request: {
  harness: Harness;
  cwd: string;
  prompt: string;
  resume?: AgentSessionRef | undefined;
}) {
  "use step";
  const runner = await createAgentRunner(request.harness, {
    cwd: request.cwd,
    run: getWorkflowMetadata(),
    resume: request.resume,
  });
  try {
    const result = await generateText({ model: runner.model, prompt: request.prompt, temperature: 0 });
    return { text: result.text, session: runner.sessionFrom(result) };
  } finally {
    await runner.close();
  }
}

Released under the MIT License.