Assembly LineDocs

agent.ts

Compose an Assembly Line agent with static policy and synchronous runtime hooks.

Edit

agent.ts is the agent-composition entrypoint. Its defineAgent({...}) object holds static identity, policy, and limits. Its synchronous setup() function selects the compiled capabilities available to the next model request.

instructions.md remains required and always trusted. useInstructions() only appends conditional guidance; it never replaces that permanent identity.

Minimal Example

import { defineAgent, useModel, useTool } from "@assemblyline-agents/core";

export default defineAgent({
  id: "minimal-agent",
  name: "Minimal Agent",
  setup() {
    useModel("openai/gpt-5.4-mini");
    useTool("echo");
  }
});

setup() must be synchronous and side-effect free. The runtime preloads run data and conversation state, validates the result against the compiled catalog and static policy, and records the complete capability snapshot before using it. The hook API provides no asynchronous setup phase. Keep network, filesystem, and other side effects in tools or adapters.

Static Fields

FieldMeaning
id, name, descriptionStable identity and display metadata.
maxIterationsHard positive agent-loop iteration limit.
maxReasoningCeiling for useReasoning().
selfImprovementPermission policy for durable skill authoring.
dynamicAutomationsPermission policy for runtime-created automations.
dynamicConnectionsPermission and host policy for adopted connections.
contextTrusted context policy, when a custom context.ts policy is required.
metadataStatic JSON metadata.
setup()Synchronous runtime capability declaration.

Model, reasoning selection, visible tools, output schema, skills, connections, subagents, sandbox profile, event observers, and conditional instructions do not belong in static fields.

Built-in Hooks

HookEffect
useRun()Reads immutable run/message/channel/conversation/metadata/attachment metadata.
usePersistentState(key, initial)Reads conversation-scoped JSON control state and returns an async setter.
useModel(model)Selects exactly one model.
useReasoning(level)Selects effort within maxReasoning.
useInstructions(text)Appends trusted instructions in call order.
useTool(name)Enables a compiled tool.
useSkill(name)Activates a compiled skill.
useConnection(name)Selects a compiled connection; grants and approvals still apply.
useSubagent(name)Exposes a compiled subagent.
useSandbox(name)Selects a compiled sandbox profile; acquisition stays lazy.
useOutputSchema(schema)Selects the runtime-enforced final-output contract.
useEvent(type, handler)Registers an after-persist observer for this run.

Set-like hooks deduplicate by compiled name. Repeated useModel(), useReasoning(), useSandbox(), or useOutputSchema() calls must agree. Conditional calls are valid: state identity comes from explicit keys, not hook position.

Capability names, event types, models, reasoning levels, and state keys passed to hooks must be string literals so the compiler can audit them. Custom hooks are ordinary synchronous functions:

function useVerifiedCustomer() {
  const [verified] = usePersistentState("customer.verified", false);
  useTool("verify_customer");
  if (verified) useTool("issue_refund");
  return verified;
}

There is no hook registry or special directory. Calling a built-in hook outside setup() (or a function called by it) throws an actionable error.

Conditional Capabilities

import {
  defineAgent,
  useInstructions,
  useModel,
  useRun,
  useTool
} from "@assemblyline-agents/core";

export default defineAgent({
  setup() {
    const run = useRun();
    if (run.metadata?.tier === "trial") {
      useModel("openai/gpt-5.4-mini");
      useTool("search_docs");
      useInstructions("Do not access billing information.");
      return;
    }
    useModel("openai/gpt-5.4");
    useTool("search_docs");
    useTool("lookup_account");
  }
});

Every possible named capability must already exist in the compiled catalog. Hooks can narrow static policy but cannot bypass host restrictions, connection authorization, tool approvals, sandbox policy, or subagent declarations.

Durable State And Re-evaluation

usePersistentState() stores small JSON control values such as workflow stages. Do not use it for secrets, files, transcripts, or long-form memory. Each key may contain at most 200 characters. Each value may serialize to at most 16,384 characters. A conversation snapshot may contain at most 256 keys and 262,144 serialized characters.

The hook returns the current value and an async setter. Call the setter from a tool or event handler, never during setup(). Tools can also update the same state through ctx.agentState:

async execute(input, ctx) {
  await saveDiagnosis(input);
  await ctx.agentState.set("triage.stage", "report");
  return { saved: true };
}

The write is atomic, increments the conversation revision, emits an agent.state_changed event with the key, revision, and either a value hash or a deletion marker, and marks the active snapshot dirty. Pass expectedRevision to ctx.agentState writes when concurrent changes must fail instead of overwriting each other. The runtime lets the current tool finish, then re-evaluates setup() before the next model request. Model, prompt, tools, connections, subagents, sandbox, and output schema change only at that boundary. One run may record at most 50 capability snapshots.

Event Observation

import { defineAgent, useEvent, useModel } from "@assemblyline-agents/core";

export default defineAgent({
  setup() {
    useModel("openai/gpt-5.4-mini");
    useEvent("run.completed", recordCompletion);
  }
});

The callback runs after its event is durable. Exact event handlers run before "*" handlers. Failure emits agent.event_handler_failed and does not fail the run. Re-evaluation replaces registrations instead of accumulating them.

Structured Outputs

Call useOutputSchema(schema) in setup(). The runtime adds the schema to the trusted prompt, validates the final JSON, performs bounded corrective retries, and exposes the parsed value as RunAgentResult.output. maxIterations remains a static hard limit.

On this page