Open Agent Loops
API Reference

API Reference

@open-agent-loops/core


Public surface of the lightweight agent core — the single entry point you import from.

Remarks

Composition over inheritance: every piece sits behind an interface that you satisfy with a plain object/function, then optionally wrap with a decorator (the with* helpers) — never subclassed. The four interfaces you implement or supply:

The streaming test double (MockModelClient) lives in ./mocks/mock-model; it is a testing utility imported directly by tests, not part of this published surface.

Example

Minimal run

import { runAgent, SessionMemoryStore, defineTool } from "@open-agent-loops/core";

const result = await runAgent({
  model,                       // your ModelClient
  memory: new SessionMemoryStore(),
  sessionId: "demo",
  tools: [searchTool(backend)],
  prompt: "Find the TODOs in this repo.",
});
console.log(result.newMessages); // messages produced by this run

See

  • runAgent — the loop entry point.
  • ToolRegistry — build a tool catalog and resolve subsets by name.

Core

NameDescription
BoundedBufferA bounded FIFO buffer with a pluggable OverflowPolicy. See the module:primitives/bounded-buffer | module docs for the backpressure model.
MessageQueueA FIFO queue of Messages for the loop's steering / follow-up seams — the unbounded specialization of BoundedBuffer (capacity: Infinity), so the overflow policy never engages and it behaves as a plain FIFO.
BoundedBufferOptionsOptions for a BoundedBuffer.
MessageQueueOptionsOptions for a MessageQueue.
PushResultThe outcome of a push, item-by-item, so a caller can react to backpressure (notify, retry, or slow its producer). The four arrays are disjoint and together account for every pushed item — except under { coalesce }, where a folded arrival is counted as accepted.
RunAgentOptionsInputs for a single runAgent run.
RunResultThe outcome of a runAgent run.
DrainModeHow many queued items a drain releases: "one-at-a-time" (the oldest single item) or "all" (every queued item). Mirrors pi's steeringMode / followUpMode.
OverflowPolicyWhat happens to an item pushed into a BoundedBuffer that is already at capacity. The four cases are genuinely distinct — they differ on whether the arrival is kept and whether the producer is asked to slow down:
prepareRequestMessagesPrepare working history for sending: drop both reasoning representations (reasoning and reasoning_details) from assistant turns that did NOT call tools.
runAgentRun the agentic loop for one session until it reaches a stopping point.

Hooks & Gating

InterfaceDescription
GateDecisionThe gate's verdict for one call: run it, or block it with a reason.
HooksLifecycle hooks for guardrails and context shaping.
ToolGateRequestOne tool call presented to the gate, with its validated arguments.
ToolResultOverrideWhat a Hooks.afterToolCall hook returns to override a result.

Messages & Events

NameDescription
AgentEventTypeDiscriminant tags for AgentEvent.
FinishReasonWhy a model turn ended — the wire finish_reason from the provider.
ReasoningFormatProvider dialect a ReasoningDetail block is encoded in.
RoleConversation roles.
ToolCallTypeThe kind of tool call.
AssistantMessageA model (assistant) turn.
AudioPartAn audio content part: base64-encoded audio the model transcribes / reasons over. Only wav and mp3 are accepted by the chat-completions audio input.
FilePartA file content part (e.g. a PDF): either inline base64 data, or a reference to a file already uploaded to the provider.
ImagePartAn image content part: a URL the model fetches, or an inline data: URI (data:image/png;base64,...).
ReasoningDetailBaseOne structured reasoning block, preserved VERBATIM for replay.
ReasoningEncryptedDetailAn encrypted reasoning block — opaque ciphertext, never decoded by this library.
ReasoningSummaryDetailA provider-summarized reasoning block (the raw chain-of-thought is withheld).
ReasoningTextDetailA plaintext (optionally signed) reasoning block.
SystemMessageA system-prompt turn.
TextPartA plain-text content part — the array-form counterpart to a bare content string. Several may appear interleaved with image/audio/file parts.
ToolCallA tool invocation requested by the model.
ToolMessageA tool-result turn — the response to a single ToolCall.
UserMessageA user turn.
AgentEventAn event emitted by the loop for observability / streaming to a UI.
AgentEventBodyThe payload of an event, minus the timestamp.
ContentPartOne part of a multimodal UserMessage content array — text, image, audio, or file — discriminated on type.
EventSinkConsumer callback for AgentEvents emitted during a run.
MessageA single conversation message — one of UserMessage, SystemMessage, AssistantMessage, or ToolMessage, discriminated by its role.
ReasoningDetailA structured reasoning block in one of its three shapes.
ToolArgumentsTool-call arguments parsed into an object.
assistantMessageConstruct an AssistantMessage — pins the role discriminant and stamps timestamp with the construction time; you supply the rest. Everything but content is optional (reasoning, reasoning_details, finishReason, tool_calls, isError, and an overriding timestamp).
audioPartConstruct an AudioPart from base64 audio bytes.
contentToTextFlatten a `string
filePartConstruct a FilePart — inline file_data (+ filename) or a file_id reference.
imagePartConstruct an ImagePart from a URL or data: URI.
isAssistantMessageNarrow a Message to an AssistantMessage.
isToolMessageNarrow a Message to a ToolMessage.
systemMessageConstruct a SystemMessage — pins the role discriminant and stamps timestamp with the construction time; you supply the rest (content, and a timestamp of your own to override the default).
textPartConstruct a TextPart.
toolMessageConstruct a ToolMessage — pins the role discriminant and stamps timestamp with the construction time; you supply the rest. tool_call_id stays required (the message is meaningless without the call it answers); toolName, isError, and an overriding timestamp are optional.
userMessageConstruct a UserMessage — pins the role discriminant and stamps timestamp with the construction time; you supply the rest (content, and a timestamp of your own to override the default).

Model

NameDescription
StreamEventTypeDiscriminant tags for StreamEvent.
ModelClientThe single LLM boundary the loop depends on.
ModelRequestEverything the model needs to produce the next assistant turn.
ReasoningProfileWhat a model family's chat template understands about reasoning.
ToolSpecTool description handed to the model so it knows what it can call.
ModelStreamA live model response: async-iterable of events.
StreamEventIncremental output from the model.
ThinkingModeDesired thinking state for a request.
injectReasoningKwargsMerge the derived chat_template_kwargs into an OpenAI chat-completions request body, keyed by its own model field. The seam a proxy uses to inject thinking control without the client knowing the per-family dialect.
reasoningKwargsForResolve the chat_template_kwargs to send for a model's thinking state, or undefined to inject nothing (unknown / non-reasoning model, or an always-on model with no toggle).
reasoningProfileForLook up the ReasoningProfile for a model id, or undefined when no family rule matches (unknown model — treat as non-reasoning).

Defining Tools

NameDescription
ExecutionModeHow a tool runs relative to its sibling calls in the same turn.
ToolA tool the agent loop can call: name, description, argument schema, and handler.
ToolContextPer-call context the loop passes to a tool's execute handler.
ToolResultWhat a tool hands back to the loop.
defineToolAuthor a tool while preserving the schema's inferred argument type for execute.
toToolSpecConvert a tool to the spec shape the model client advertises.
validateToolArgumentsValidate a tool call against the tool's schema, returning the parsed arguments.

Tool Registry

ClassDescription
ToolRegistryA named collection of tools you build once and resolve from by name.

Built-in Tools

NameDescription
BrowserElementOne interactive element exposed in a BrowserSnapshot.
BrowserSessionThe browser capability seam — implement this against a real browser.
BrowserSnapshotA structured view of the page after a browser action.
CodeExecutionBackendThe code-execution capability seam — implement this against a sandbox.
CodeExecutionRequestA request to run a snippet of code in some language.
CodeExecutionResultThe outcome of running one code snippet.
FileEditRequestA request to replace the first occurrence of a string in a file.
FileEditResultThe outcome of an edit.
FileReadBackendThe read-only filesystem capability seam — implement this against your host.
FileReadRequestA request to read a slice of a file.
FileReadResultThe selected slice of a file's contents.
FileWriteBackendThe mutating filesystem capability seam — implement this against your host.
FileWriteRequestA request to write a file's full contents.
FileWriteResultThe outcome of writing a file.
GlobQueryA request to list files matching a glob pattern.
SearchBackendThe regex-search capability seam — implement this against your host.
SearchMatchA single content match from a regex search.
SearchQueryA regex search request handed to the backend.
ShellBackendThe shell capability seam — implement this against your host.
ShellResultThe outcome of running one shell command.
WebBackendThe read-only web capability seam — implement this against an online service.
WebFetchRequestA request to fetch one URL's contents.
WebFetchResultThe contents fetched from a URL.
WebSearchQueryA web-search request handed to the backend.
WebSearchResultA single hit from a web search.
browserToolsBuild the browser_navigate, browser_click, and browser_type tools over a BrowserSession.
codeExecutionToolBuild a code_execution tool bound to a backend.
editToolBuild an edit tool bound to a backend.
formatBrowserSnapshotRender a page snapshot into the single text block handed to the model.
formatCodeExecutionResultFold a CodeExecutionResult into the single text result the loop hands to the model.
formatEditResultRender an edit outcome into the single text block handed to the model.
formatFileContentRender a file slice into the single text block handed to the model.
formatGlobMatchesRender glob matches into the single text block handed to the model.
formatSearchResultsRender search matches into the single text block handed to the model.
formatShellResultFold a ShellResult into the single text result the loop hands to the model.
formatWebFetchResultRender a fetched page into the single text block handed to the model.
formatWebSearchResultsRender web-search hits into the single text block handed to the model.
formatWriteResultRender a write outcome into the single text block handed to the model.
globToolBuild a glob tool bound to a backend.
readToolBuild a read tool bound to a backend.
searchToolBuild a search tool bound to a backend.
shellToolBuild a shell tool bound to a backend.
webFetchToolBuild a web_fetch tool bound to a backend.
webSearchToolBuild a web_search tool bound to a backend.
writeToolBuild a write tool bound to a backend.

Stop Conditions

NameDescription
StopContextThe per-turn snapshot passed to every StopCondition.
StopConditionA predicate that decides whether the loop should stop after the current turn.
allCombine conditions: stop only if ALL of them say so.
anyCombine conditions: stop if ANY of them say so.
maxStepsBuild a condition that stops once step reaches n turns.
notInvert a condition.
whenToolCalledBuild a condition that stops as soon as a specific tool has been called this turn.

Memory

NameDescription
SessionMemoryStorePersistence seam for per-session message history.
MemoryPersistence seam for per-session message history.
MemoryListenerObserve a Memory without changing its behavior.

Permissions

NameDescription
ApprovalChoiceWhat the user picked when prompted: scoped to this call, or remembered.
PermissionPolicyA configured policy for a tool: allow silently, deny silently, or ask.
InMemoryPermissionStoreRAM-backed PermissionStore with a fallback policy and seeded rules.
ApprovalPrompterAsks the user to approve calls whose policy is "ask".
ApprovalRequestOne call the user is being asked to approve.
InMemoryPermissionStoreOptionsOptions for InMemoryPermissionStore.
PermissionStoreThe configuration the gate consults.
SettablePolicyA policy that can be seeded into a store: a concrete decision, never PermissionPolicy.Ask.
permissionGateBuild a gateToolCalls hook from a permission store and an approval prompter.

Credentials

NameDescription
InMemoryCredentialStoreRAM-backed CredentialStore seeded from a record of secrets.
CredentialStoreA lookup table resolving a placeholder name to its secret value.
InMemoryCredentialStoreOptionsOptions for InMemoryCredentialStore.
withCredentialsWrap a Tool so {{name}} placeholders in its args are resolved from a CredentialStore and scrubbed back out of its output.

Composition

NameDescription
ModelGateA pre-call admission gate awaited before each model request.
withMemoryListenersWrap a Memory so a MemoryListener is notified after each operation.
withMemoryNamespaceWrap a Memory so every session id is namespaced under prefix.
withModelGateWrap a ModelClient so a ModelGate runs before each stream — the "can I make this call?" seam.
withModelObserverWrap a ModelClient to observe every stream event as it flows through.

Channels

NameDescription
ChannelBridgeConnects a ChannelSource to a Dispatcher. Construct it, then start; stop to tear down.
DispatcherTurns submit(sessionId, message) calls into throttled runAgent runs. See the module:channels/dispatcher | module docs for the model.
InMemoryChannelSourceA ChannelSource backed by in-memory arrays. No I/O, no timers — perfect for tests and the runnable example.
ChannelBridgeOptionsOptions for a ChannelBridge. The throttling knobs are forwarded to the dispatcher the bridge creates.
ChannelSourceA live channel transport. Implementations: SlackSource, DiscordSource, …; InMemoryChannelSource is the test/example fake.
DispatcherOptionsOptions for a Dispatcher.
InboundMessageA normalized inbound message — the single shape every transport maps its provider events into, so the rest of the system is channel-agnostic.
OutboundTargetWhere a reply is posted back — the channel/thread a run's output returns to.
DispatcherRunBaseThe per-run configuration shared across every session the dispatcher drives — everything runAgent needs except the per-call sessionId, prompt, and signal, which the dispatcher supplies itself.
RunFnHow the dispatcher executes one run. Defaults to runAgent; injectable so tests can drive it with a controllable fake instead of a real model.

Classes

ClassDescription
AsyncWriter-
Tracer-

Functions

FunctionDescription
defaultSessionIdThe default thread → sessionId mapping: one conversation per thread (falling back to the channel when a provider doesn't thread). Override via ChannelBridgeOptions.sessionIdFor for per-channel or per-user grain.

Goal Loop

NameDescription
GoalResultThe outcome of a runGoal run.
GradeA grader's verdict on one round.
GradeContextThe per-round snapshot handed to a Grader after a round's inner run settles.
ModelGraderOptionsConstruction options for modelGrader.
RunGoalOptionsInputs for a single runGoal run.
GraderJudges a round and decides whether the goal is met.
RunGoalRunBaseThe per-round run configuration shared across every round — everything runAgent needs except the prompt (which runGoal re-prompts each round) and the signal (which runGoal forwards). The sessionId lives here and is reused for every round, so each round loads the prior rounds' history.
modelGraderBuild a Grader backed by a model.
runGoalPursue a goal across rounds, driving runAgent until a Grader is satisfied or the round cap is reached.

Interfaces

InterfaceDescription
AsyncWriterOptionsAsyncWriter — a fire-and-forget, queued, batched JSON-line writer for traces.
DisclosureStepOne turn of the progressive-disclosure timeline: what was disclosed to the model this turn, and what changed since the previous turn. Built by diffing consecutive RequestSnapshots.
DispatcherStatsAggregate backpressure readings across all of a Dispatcher's sessions.
FormatOptions-
RawRequestThe fully assembled request body captured off the wire (request side) — one per model turn, the exact JSON POSTed to the endpoint. Carries the whole conversation as sent: messages (system folded in, every assistant tool_calls block and tool result), the available tools, sampling params, and chat_template_kwargs. With TraceMeta.baseURL it's enough to reconstruct a reproducible curl for the call. Captured by the onRawRequest tap; the request-side twin of RawSSE.
RawSSEA raw SSE line captured off the wire (response side).
RequestSnapshotA snapshot of what was disclosed to the model on one request (one turn) — captured by observe(), which sees every ModelRequest. Tracing these across a run is how you watch progressive disclosure: the tool surface, the system prompt, and the size of the context window as they change turn to turn.
SentReplyOne reply the source was asked to post — recorded for inspection.
ToCurlOptionsOptions for toCurl.
TraceDocumentThe full trace as one JSON-serializable document: run config + timeline.
TraceEntryOne timestamped record in a trace.
TraceMetaRun-level configuration captured alongside the timeline — the context you need to reproduce or compare a run. Filled in from whatever taps are wired: sessionId from the agent's agent_start, system/tools from the model request (via observe), and model/params/system from a provider's onRequest tap (e.g. OpenAICompatibleModel).
TracerOptions-
TrajectoryStepOne turn of the agent's trajectory: the model's action paired with the observations it produced. assistant is the action (text and/or tool calls); tools are the observations (each call's result).
TrajectoryToolOne tool invocation within a turn: the call and its outcome.

Multi-Agent

NameDescription
AgentAsToolOptionsOptions for agentAsTool.
agentAsToolWrap an agent as a Tool another agent can call.

Observability

FunctionDescription
toCurlRender a captured request body as a runnable curl command.

Planning Tools

NameDescription
InMemoryScratchpadIn-memory Scratchpad — the shipped default.
InMemoryTodoStoreIn-memory TodoStore — the shipped default.
ScratchpadThe scratchpad seam — a single slot of free-form text the agent reads and overwrites.
TodoItemA single to-do item.
TodoStoreThe to-do store seam — the state behind the three tools.
TodoStatusA to-do status: one of TODO_STATUSES.
RETRY_LIMITHow many times a failed task may be retried before the tool tells the agent to stop and escalate to the user.
TODO_STATUSESThe lifecycle states a TodoItem can be in.
formatTodoListRender a to-do list into the text block handed to the model: a header, a per-status count line, then one line per item (with a retry note when > 0).
scratchpadToolsBuild the read_scratchpad and write_scratchpad tools over a Scratchpad.
todoListToolsBuild the todo_append, todo_list, and todo_update tools over a TodoStore.

Skills

NameDescription
SkillRegistryA named collection of skills you build once and resolve from by name.
SkillA named bundle of instructions and tools the agent can pull in on demand.
SkillResourceA bundled reference the model can pull in on demand — the third level of progressive disclosure, below Skill.instructions.
skillResourceToolBuild the skill_resource tool bound to a SkillRegistry: Level 3 disclosure, loading one of a skill's bundled resources on demand.
skillToolBuild the skill tool bound to a SkillRegistry.

Type Aliases

Type AliasDescription
CompactEntryCompact serialization of a TraceEntry — the on-disk / wire shape. The data payload is flattened up, and the two redundant fields are dropped: label (always equals data.type) and the absolute t (reconstruct it from the document's startedAt + this entry's dt). The in-memory TraceEntry keeps the richer shape for programmatic access; only JSON output is compacted.
TraceSourceOrigin seam of a trace entry.

On this page