Agent API map

July 29, 2026 · View on GitHub

NeedJS APIGuide
Define an agentAgent, agent(), AgentDec/agentsFromAgents, Agent definition
Define toolstool(), built-in tool factories, Tool/toolsFromTools
Run lifecycle operationsAgentRuntime, module-level helpersRuntime, Deploy/serve/run/plan
Control an executionAgentClient, AgentHandle, ClientHandleControl plane
Add safety controlsguardrail and termination classesGuardrails, Termination
Compose agentsStrategy, handoffs, plan_executeMulti-agent
Bridge frameworksframework detection + subpath wrappersFramework bridges

The public surface of @io-orkes/conductor-javascript/agents. Everything below is exported from the package root unless noted.

tool() and built-in tools

tool(fn: (args, ctx?: ToolContext) => Promise<T>, options: ToolOptions): ToolFunction

ToolOptions: { name?, description, inputSchema, outputSchema?, approvalRequired?, timeoutSeconds?, external?, credentials?, guardrails?, maxCalls?, retryCount?, retryDelaySeconds?, retryPolicy? }. inputSchema/outputSchema accept a Zod schema or a JSON Schema object.

Built-in tool builders (all return a ToolDef):

BuilderRequired optionstoolType
httpToolname, description, url (method?, headers?, inputSchema?, credentials?)http
mcpToolserverUrl (name?, headers?, toolNames?, maxTools?, credentials?)mcp
apiToolurl (name?, headers?, toolNames?, maxTools?, credentials?)api
agentToolagent (name?, description?, retryCount?, retryDelaySeconds?, optional?)agent_tool
humanToolname, description (inputSchema?)human
imageToolname, description, llmProvider, model (style?, size?)generate_image
audioToolname, description, llmProvider, model (voice?, speed?, format?)generate_audio
videoToolname, description, llmProvider, model (duration?, resolution?, fps?, ...)generate_video
pdfTool— (name?, description?, pageSize?, theme?, fontSize?)generate_pdf
waitForMessageToolname, description (batchSize? def 1, blocking? def true)pull_workflow_messages
searchToolname, description, vectorDb, index, embeddingModelProvider, embeddingModel (namespace?, maxResults?, dimensions?)rag_search
indexToolname, description, vectorDb, index, embeddingModelProvider, embeddingModel (namespace?, chunkSize?, chunkOverlap?, dimensions?)rag_index

Discovery / helpers: Tool(options?) decorator + toolsFrom(instance); getToolDef(obj) / normalizeToolInput(obj) (extract a ToolDef from a tool() wrapper, Vercel AI tool, or raw def); isZodSchema(obj).

ToolContext

Passed as the second arg to a tool() function:

interface ToolContext {
  sessionId: string;
  executionId: string;
  agentName: string;
  metadata: Record<string, unknown>;
  dependencies: Record<string, unknown>;
  state: Record<string, unknown>;   // mutable; mutations propagate between tool calls
}

Guardrails

  • guardrail(fn, { name, position?, onFail?, maxRetries? }) — custom guardrail from a function returning { passed, message?, fixedOutput? }. guardrail.external({ name, position?, onFail? }) for remote-worker guardrails.
  • new RegexGuardrail({ name, patterns, mode, position?, onFail?, message?, maxRetries? })mode: 'block' | 'allow'. .toGuardrailDef().
  • new LLMGuardrail({ name, model, policy, position?, onFail?, maxRetries?, maxTokens? }) — server-side LLM judge. .toGuardrailDef().
  • Guardrail(options?) decorator + guardrailsFrom(instance).

position: 'input' | 'output' (default 'output'). onFail: 'raise' | 'retry' | 'fix' | 'human' (default 'raise'). Attach via agent.guardrails or tool(fn, { guardrails }).

Termination

All extend TerminationCondition and compose via .and(other) / .or(other) (or variadic AndCondition(...) / OrCondition(...)).

ClassConstructor
TextMention(text, caseSensitive = false)
StopMessage(stopMessage)
MaxMessage(maxMessages)
TokenUsageCondition({ maxTotalTokens?, maxPromptTokens?, maxCompletionTokens? })
AndCondition / OrCondition(...conditions)

Handoffs

  • new OnTextMention({ target, text }) — hand off when output mentions text (case-insensitive).
  • new OnToolResult({ target, toolName, resultContains? }) — hand off after a tool returns.
  • new OnCondition({ target, condition, agentName? }) — hand off when a predicate (runs as a worker) returns true.
  • new TextGate({ text, caseSensitive? }) — gate on text containment (gate: option).
  • gate(fn, { agentName? }) — custom gate from a function.

HandoffContext (passed to conditions): { result, toolName?, toolResult?, messages? }.

Callbacks

Subclass CallbackHandler and override hooks (each runs as a server worker):

abstract class CallbackHandler {
  onAgentStart?(agentName, prompt): Promise<void>;
  onAgentEnd?(agentName, result): Promise<void>;
  onModelStart?(agentName, messages): Promise<void>;
  onModelEnd?(agentName, response): Promise<void>;
  onToolStart?(agentName, toolName, args): Promise<void>;
  onToolEnd?(agentName, toolName, result): Promise<void>;
}

CALLBACK_POSITIONS maps hook names to wire positions; getCallbackWorkerNames(agentName, handler) lists registered worker names.

Schedules / SchedulerClient

new Schedule({ name, cron, timezone?, input?, catchup?, paused?, startAt?, endAt?, description? })

Agent schedules ride the SDK SchedulerClient (also available via OrkesClients.getSchedulerClient()). Its typed lifecycle methods: save(schedule, agentName), get(wireName, agentName?), listForAgent(agentName), pause(wireName, reason?), resume(wireName), delete(wireName), runNow(info), previewNext(cron, { n?, startAt?, endAt? }), reconcile(agentName, desired) — plus the endpoint-level wrappers (saveSchedule, getSchedule, pauseSchedule, ...). Pause/resume issue PUT first and fall back to GET on HTTP 405 (per-schedule verbs differ by Conductor server family), so one client works against both OSS/embedded and Orkes servers.

The schedules namespace is a convenience layer over the singleton runtime: schedules.list({ agent }), .get(name, { runtime? }), .pause(name, { reason?, runtime? }), .resume, .delete, .runNow, .previewNext(cron, { n? }), .save(schedule, agent). Lifecycle calls key on the wire name (the prefixed name in ScheduleInfo).

Errors: ScheduleError, ScheduleNameConflict, ScheduleNotFound, InvalidCronExpression. ScheduleInfo includes name, shortName, agent, cron, timezone, paused, pausedReason, nextRun, ...

AgentResult

Returned by run() / wait().

interface AgentResult {
  output: Record<string, unknown>;   // text answer -> { result: "..." }
  executionId: string;
  correlationId?: string;
  messages: unknown[];
  toolCalls: unknown[];
  status: 'COMPLETED' | 'FAILED' | 'TERMINATED' | 'TIMED_OUT';
  finishReason: 'stop' | 'length' | 'tool_calls' | 'error' | 'cancelled' | 'timeout' | 'guardrail' | 'rejected';
  error?: string;
  tokenUsage?: { promptTokens; completionTokens; totalTokens };
  metadata?: Record<string, unknown>;
  events: AgentEvent[];
  subResults?: Record<string, unknown>;
  readonly isSuccess: boolean;   // status === 'COMPLETED'
  readonly isFailed: boolean;    // FAILED | TIMED_OUT
  readonly isRejected: boolean;  // finishReason === 'rejected'
  printResult(): void;
}

AgentHandle

Returned by runtime.start().

interface AgentHandle {
  executionId: string;
  correlationId: string;
  getStatus(): Promise<AgentStatus>;
  wait(pollIntervalMs?): Promise<AgentResult>;
  respond(output): Promise<void>;
  approve(output?): Promise<void>;
  reject(reason?): Promise<void>;
  send(message): Promise<void>;
  pause(): Promise<void>;
  resume(): Promise<void>;
  cancel(): Promise<void>;
  stop(): Promise<void>;
  stream(): AgentStream;
}

approve() sends { approved: true, ...output }; reject(reason) sends { approved: false, reason }; send(message) sends { message }. For a custom human-task response (shaped by pendingTool.response_schema), use respond(body). wait(pollIntervalMs?) rejects once its deadline passes (timeoutSeconds-derived, or 10 min default) with an AgentAPIError naming the last known status — and, for a stateful (domain-routed) run with liveness enabled, rejects earlier with WorkerStallError if the local worker appears to have died (see Liveness monitoring).

pause()/resume() here pause/resume a running execution (distinct from schedule pause/resume, which pauses a cron definition, not a live run).

AgentStream / AgentEvent

AgentStream implements AsyncIterable<AgentEvent> — iterate with for await. Methods: respond(output), approve(output?), reject(reason?), send(message), and getResult(): Promise<AgentResult> (drains the stream, polls for the terminal status, returns the result). Fields: executionId, events (accumulates).

interface AgentEvent {
  type: 'thinking' | 'tool_call' | 'tool_result' | 'guardrail_pass' | 'guardrail_fail'
      | 'waiting' | 'handoff' | 'message' | 'error' | 'done' | string;
  content?: string;
  toolName?: string;
  args?: Record<string, unknown>;
  result?: unknown;
  target?: string;          // handoff target
  output?: unknown;         // on 'done'
  pendingTool?: PendingTool;// on 'waiting'
  guardrailName?: string;
}

AgentStatus: { executionId, isComplete, isRunning, isWaiting, output?, status, reason?, currentTask?, messages, pendingTool? }. PendingTool: { taskRefName, toolCalls?: { name, args }[], response_schema?, ... }. EventTypes, Statuses, FinishReasons, TERMINAL_STATUSES enums are exported.

Errors

ConductorAgentError (base), AgentAPIError, AgentNotFoundError, ConfigurationError, CredentialNotFoundError, CredentialAuthError, CredentialRateLimitError, CredentialServiceError, SSETimeoutError, TerminalToolError, WorkerStallError, GuardrailFailedError.

SSEUnavailableError also extends ConductorAgentError but isn't exported from the package root — it's thrown internally when an SSE connection can't be established and caught by AgentStream itself to trigger the automatic polling fallback (see SSE fallback); there's no caller-visible error for this case since the fallback is transparent.

RunSettings

Per-run LLM overrides, passed as RunOptions.runSettings to run/start/stream.

interface RunSettings {
  model?: string;
  temperature?: number;
  maxTokens?: number;
  reasoningEffort?: string;
  thinkingBudgetTokens?: number;
}

RunOptions.runSettings overrides the LLM call for a single run/start/stream, without touching the agent's own config. Only set fields override; unset fields keep the agent's own serialized values, and the override doesn't cascade to sub-agents (each keeps its own settings).

const result = await runtime.run(agent, prompt, {
  runSettings: {
    model: 'anthropic/claude-sonnet-4-6', // overrides agent.model for this run
    temperature: 0.2,
    maxTokens: 4096,
    reasoningEffort: 'high',
    thinkingBudgetTokens: 8000,           // maps to the wire thinkingConfig shape
  },
});

// RunOptions.model is sugar for runSettings.model -- an explicit runSettings.model wins:
await runtime.run(agent, prompt, { model: 'openai/gpt-4o-mini' });

Credentials and secrets

Pass credential names with credentials: [...] at the agent level and/or per tool. The server resolves secrets when it polls each task and delivers them wire-only, on that task's runtimeMetadata — never persisted, never fetched by the worker separately. The SDK injects them into the worker's process.env for the duration of the call (mutate-invoke-restore, serialized so concurrent calls don't clobber each other's env). For HTTP/MCP tools, reference them inline in headers with ${NAME} substitution.

Fail-closed, no fallback: if a tool declares credentials: [...] and the server didn't deliver one of them on runtimeMetadata (e.g. an older server that predates TaskDef.runtimeMetadata support), the task fails with a non-retryable error naming the missing credential. There is no ambient-env fallback to silently read a locally-set variable instead.

import { Agent, tool, httpTool, getCredential } from '@io-orkes/conductor-javascript/agents';

// A worker tool: the secret is injected into the worker's process.env for the call
const dbLookup = tool(
  async (args: { query: string }) => {
    const key = process.env.DB_API_KEY ?? '';
    return { ok: key !== '' };
  },
  {
    name: 'db_lookup',
    description: 'Look up data.',
    inputSchema: { type: 'object', properties: { query: { type: 'string' } }, required: ['query'] },
    credentials: ['DB_API_KEY'],
  },
);

// Or fetch a credential explicitly inside a tool
const analytics = tool(
  async (args: { topic: string }) => {
    const key = await getCredential('ANALYTICS_KEY');
    return { topic: args.topic, ok: !!key };
  },
  { name: 'analytics', description: 'Query analytics.', inputSchema: {
    type: 'object', properties: { topic: { type: 'string' } }, required: ['topic'],
  }, credentials: ['ANALYTICS_KEY'] },
);

// HTTP tool with ${CRED} header substitution
const searchApi = httpTool({
  name: 'search_api',
  description: 'Search.',
  url: 'https://api.example.com/search',
  headers: { Authorization: 'Bearer ${SEARCH_API_KEY}' },
  credentials: ['SEARCH_API_KEY'],
});

const agent = new Agent({
  name: 'credentialed_agent',
  model: 'anthropic/claude-sonnet-4-6',
  instructions: '…',
  tools: [dbLookup, analytics, searchApi],
  credentials: ['DB_API_KEY', 'ANALYTICS_KEY', 'SEARCH_API_KEY'],
});

You can also pass credentials at call time: runtime.run(agent, prompt, { credentials: ['X'] }).

Skills

skill(path, options?) loads a SKILL.md skill directory as an Agent; loadSkills(dir) loads every skill subdirectory keyed by name. Skills are framework agents (_framework: "skill") and run via the same run() path; they can be wrapped with agentTool and used inside other agents.

import { skill, loadSkills, agentTool, Agent } from '@io-orkes/conductor-javascript/agents';

const reviewer = skill('./skills/code-review', { model: 'openai/gpt-4o' });
const all = loadSkills('./skills');          // Record<string, Agent>

const orchestrator = new Agent({
  name: 'lead',
  model: 'anthropic/claude-sonnet-4-6',
  instructions: 'Delegate reviews to the code-review skill.',
  tools: [agentTool(reviewer)],
});

Other exports

  • Memory: ConversationMemory, SemanticMemory, InMemoryStore — see Stateful agents: Memory.
  • Plans: Plan, Step, Op, Generate, Validation, Action, Ref, Context, coercePlan — see Plans / PLAN_EXECUTE.
  • Liveness: LivenessMonitor, LivenessMonitorOptions — see Liveness monitoring.
  • Code execution: LocalCodeExecutor, DockerCodeExecutor, JupyterCodeExecutor, ServerlessCodeExecutor, CodeExecutor, CommandValidator.
  • Claude Code: ClaudeCode(modelName?, permissionMode?), PermissionMode, resolveClaudeCodeModel.
  • Extended agents: GPTAssistantAgent({ name, assistantId, model?, instructions? }).
  • Framework integration: detectFramework, serializeFrameworkAgent, serializeLangGraph, serializeLangChain — see Framework bridges.
  • Subpath exports: @io-orkes/conductor-javascript/agents/vercel-ai, @io-orkes/conductor-javascript/agents/langgraph, @io-orkes/conductor-javascript/agents/langchain, @io-orkes/conductor-javascript/agents/testing.

Next steps

See agent definition for Agent/AgentOptions, and runtime/client for the two ways to execute one.