Skip to content

GthLangChainAgent

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthLangChainAgent.ts:333

Lean agent: builds a standard createAgent (ReAct) graph. All run/stream/event plumbing lives in GthAbstractAgent; this class only knows how to construct the graph in init.

new GthLangChainAgent(statusUpdate, resolvers?): GthLangChainAgent

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:327

StatusUpdateCallback

AgentResolvers

GthLangChainAgent

GthAbstractAgent.constructor

protected agent: GthCompiledGraph | null = null

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:255

GthAbstractAgent.agent


protected command: GthCommand | undefined = undefined

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:257

GthAbstractAgent.command


protected config: GthConfig | null = null

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:256

GthAbstractAgent.config


debugCapture: DebugCapture | undefined

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:279

Opt-in debug sink for the TUI /debug panel. Set AFTER init via runner.getAgent(); read lazily inside each backend’s wrapModelCall capture middleware so that when it is undefined (the normal path) the middleware is a transparent pass-through. Lives on the base so every backend supports it; the AG-UI server / non-TUI callers simply never set it, so those contracts are unchanged.

GthAbstractAgent.debugCapture


protected displayCommand: string | undefined = undefined

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:270

GS2-95 — the name of the command the USER typed, as the run header should say it. Set from GthAgentInitOptions#displayCommand by the backend’s init, and read by exactly one thing: compactHeaderStatus.

Separate from command because that field is not a label — it selects the mode prompt, the approvals posture and the command-specific filesystem config. Naming the header off it is why gth eval used to open with ask, and moving it to fix the header would silently change which system prompt those runs execute under. Left undefined by every command whose init verb IS its name, which is most of them.

GthAbstractAgent.displayCommand


lastModelRequest: LastModelRequest | undefined

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:289

GS2-56 — the ALWAYS-ON snapshot of the most recent model request (extras + the as-sent, post-summarization messages), populated UNCONDITIONALLY at each backend’s wrapModelCall feed site — NOT gated on debugCapture being attached. This is what lets /debug-dump render the full model input even when the TUI /debug panel was never opened and on non-TUI surfaces (the sink only ever fed the live /debug panel). O(1): a single overwritten reference retaining only the LAST call — no accumulation, so the “pay nothing until you need it” intent is kept.

GthAbstractAgent.lastModelRequest


protected raterClarifications: Set<string>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:1046

[[TUI-C69]] — the ids noteRaterClarification has been told about this turn.

GthAbstractAgent.raterClarifications


protected resolvers: AgentResolvers | undefined

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:254

GthAbstractAgent.resolvers


protected statusUpdate: StatusUpdateCallback

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:253

GthAbstractAgent.statusUpdate

get protected headerRung(): "none" | "compact" | "debug"

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:343

GS2-101 — the run-header rung in force. An unset output.header resolves to compact: a run that was never configured opens with one attribution line and nothing else, and the technical preamble is opt-in via output.header: 'debug'.

Defaulted HERE rather than in DEFAULT_CONFIG (the convention injectModelContext and debugDump.redact also follow) so the effective-config snapshot gth config prints does not grow a key nobody set.

"none" | "compact" | "debug"

GthAbstractAgent.headerRung

cleanup(): Promise<void>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:1339

Promise<void>

GthAbstractAgent.cleanup


clearRaterClarifications(): void

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:1041

[[TUI-C69]] §5.4 — forget the noted ids, called at the top of every turn and on /clear.

The set is keyed on tool-call ids, and an id is only meaningful while the result carrying it is being rendered. Holding them past that costs a string per rater rejection for the life of the process — small — and risks the thing that is not small: a LATER call that reuses a noted id renders as a clarification request whatever it actually was, so a successful command inherits the tone of an argument it had no part in.

That reuse is not reachable with the providers installed today — @langchain/ollama mints v4() uuids, @langchain/google lc-tool-call-${v4()}, and OpenAI and Anthropic supply their own unique ids — but the protection was the providers’, not this code’s, which is a property no test here can hold and no bump has to preserve.

On /clear it is the same argument GthAgentRunner.resetThread makes about the negotiation: state from before the user asked for the conversation to be forgotten must not decide how the conversation after it is drawn.

void

GthAbstractAgent.clearRaterClarifications


protected compactHeaderStatus(): void

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:384

GS2-93 — the compact rung’s whole output: one line naming the command and the model that served it, in place of the preamble. Called once from the backend’s init, after the command and effective config are in place. The string is runHeaderLine’s, shared with the review document’s opening line so the two writers cannot drift.

This renders; it does not decide. The word after the product name is displayCommand when the command supplied one and the init verb otherwise — GS2-93 forbids a label table inside the agent, because naming a user-facing line is the command’s call, not the runtime’s.

Two runs deliberately emit nothing here:

  • review and pr already open with reviewHeadingBlock, which renders this same line. Emitting here as well would print the header twice on one screen.
  • A run with no name at all — the pr command’s discovery sub-agent is the one such caller, and it runs inside a pr whose header is already on screen. The name is what this line is for, so with none there is nothing to say; inventing a word for it would be naming a user-facing surface from inside the agent.

The model half is the shared modelProviderLabel spelling (DL-6), and it is dropped rather than faked when nothing resolves (DL-7), leaving the command on its own.

void

GthAbstractAgent.compactHeaderStatus


protected extractAndFlattenTools(tools): StructuredToolInterface<ToolInputSchemaBase, any, any>[]

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:1379

Extract and flatten tools from toolkits, applying client-tool interrupt() stubbing. A tool with metadata.client === true has its body swapped for an interrupt() call so the run suspends and the client fulfils it (the C-a AG-UI bridge depends on this).

(StructuredToolInterface<ToolInputSchemaBase, any, any> | BaseToolkit | ServerTool)[]

StructuredToolInterface<ToolInputSchemaBase, any, any>[]

GthAbstractAgent.extractAndFlattenTools


getDeclaredMcpToolAnnotations(): ReadonlyMap<string, DeclaredToolAnnotations>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:459

EXT-70 §4.7.1 — what the MCP servers declared for their tools at the last init, keyed by registered tool name (empty before it, and on a session with no MCP servers).

ReadonlyMap<string, DeclaredToolAnnotations>

GthAbstractAgent.getDeclaredMcpToolAnnotations


getEffectiveConfig(config, command): GthConfig

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:1353

GthConfig

GthCommand | undefined

GthConfig

GthAbstractAgent.getEffectiveConfig


getPendingToolInterrupts(runConfig): Promise<PendingToolInterrupt[]>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:967

Inspect the checkpointed state for the thread and return the tool calls currently pending human approval (empty array when the run finished normally). A LangGraph humanInTheLoopMiddleware interrupt parks one HITLRequest per suspended super-step in state.tasks[].interrupts[].value.actionRequests (each { name, args }); this flattens those into PendingToolInterrupts. Defensive throughout — a graph without getState, or any unexpected shape, yields [] rather than throwing, so a missing HITL setup degrades to “no approval needed” instead of breaking the run.

RunnableConfig

Promise<PendingToolInterrupt[]>

GthAbstractAgent.getPendingToolInterrupts


getRegisteredToolNames(): string[]

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:451

EXT-58 — the tool names registered with the graph at the last init (empty before it). The runner intersects these with the built-in summaries table to build the rater’s granted-alternative list, so the rater can never name a tool this session does not have.

string[]

GthAbstractAgent.getRegisteredToolNames


getRunStats(): GthRunStats

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:473

GS2-16 — the analytics harvested since the last resetRunStats. Never throws.

GthRunStats

GthAbstractAgent.getRunStats


protected headerStatus(message): void

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:356

GS2-93 — emit one line of the technical run-header preamble (the Workdir/Model/Tools/Middleware block). Only the debug rung shows it; compact replaces the whole block with compactHeaderStatus’s single line and none shows nothing. A non-debug rung only ever reaches here in non-TUI text modes: the interactive TUI forces debug before init (see createTuiSession), and the TUI event path never goes through the interrupt-hint site, so the whole preamble stays visible there. Only INFO header lines route through this — real model/tool output, warnings and errors keep using statusUpdate directly.

string

void

GthAbstractAgent.headerStatus


init(command, configIn, checkpointer?, options?): Promise<void>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthLangChainAgent.ts:334

Build the underlying compiled graph and assign it to agent. This is the part a backend implements; everything else on the base is shared.

GthCommand | undefined

GthConfig

BaseCheckpointSaver<number>

GthAgentInitOptions

Promise<void>

GthAbstractAgent.init


invoke(messages, runConfig): Promise<string>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:530

Invoke LLM with a message and runnable config. For streaming use #stream method, streaming is preferred if model API supports it. Please note that this when tools are involved, this method will anyway do multiple LLM calls within LangChain dependency.

Message[]

RunnableConfig

Promise<string>

GthAbstractAgent.invoke


noteRaterClarification(toolCallId): void

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:1019

[[TUI-C69]] §5.4 — remember that this call was bounced back to the agent as a negotiation round, so both display paths can tone its result row as a clarification request.

A plain set rather than a queue: the ids are LangChain tool-call ids, unique per call, and the two display paths read the same one without either consuming it — a session drives one of them, never both. clearRaterClarifications empties it with the rest of the turn’s state, so a long run cannot accumulate.

string

void

GthAbstractAgent.noteRaterClarification


protected processEventStream(stream): AsyncGenerator<AgentStreamEvent>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:1048

IterableReadableStream<[BaseMessage<MessageStructure<MessageToolSet>, MessageType>, Record<string, unknown>]>

AsyncGenerator<AgentStreamEvent>

GthAbstractAgent.processEventStream


protected recordRunStats(message): void

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:478

GS2-16 — fold one message (or chunk) into the run tally. Fully guarded (fail-soft).

unknown

void

GthAbstractAgent.recordRunStats


protected registerApprovalsAwareTools<T>(tools, options): T[]

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:424

EXT-58 (spec §4.5) — the ONE tool-registration hook every backend calls with its final tool array, just before handing it to the graph builder. It does two things:

  1. Appends the rung’s approval sentence to every tool that is not auto-approved at that rung, and leaves every granted tool’s description untouched (the absence of the sentence is what marks a tool free). See applyRungAwareToolDescriptions.
  2. Records the registered tool names for getRegisteredToolNames, which feeds the rater’s granted-alternative list (§4.4).
  3. EXT-70 §4.7.1 — records what the MCP servers declared about their own tools, for getDeclaredMcpToolAnnotations. This is the ONE place a tools/list annotation enters the approvals stack, and it enters as a claim: nothing here decides whether it is believed.

gatedTools MUST be the LIVE gated set for the rung in forceresolveGatedToolNames for that rung — and NOT the set the caller wires into the approval interrupt. The two are different on purpose: the interrupt is installed once, at agent init, and is deliberately rung-independent (resolveInterruptToolNames, the union over every rung) so that /approvals <mode> can move the mode underneath it for the rest of the session. Passing that wider set here would describe tools as needing approval that the live mode does not gate — and a call the live mode does not gate is auto-approved the moment it reaches the runner, so the sentence would be a promise nothing keeps.

What keeps a description from promising an approval the gate will not ask for is therefore that both this and GthAgentRunner’s own check are projections of the SAME rule, isToolGatedAtRung, evaluated against the SAME live mode — §4.5’s “a description that disagrees with what the gate will actually do is worse than no description at all”.

additionalToolNames covers tools the graph builder registers itself and that therefore never appear in tools. Their descriptions are not ours to write, so they cannot be suffixed here; they are recorded only so the rater’s suggestion list reflects what the model actually has.

T extends DescribableTool

T[]

readonly string[]

readonly string[]

"manual" | "write" | "assisted" | "auto" | "bypass"

T[]

GthAbstractAgent.registerApprovalsAwareTools


resetRunStats(): void

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:468

GS2-16 — clear the per-run analytics tally so the next turn starts from zero. The runner calls this at each turn boundary because it (and this agent) are reused across turns in an interactive session.

void

GthAbstractAgent.resetRunStats


protected setLastModelRequest(messages, extras?): void

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:297

GS2-56 — stash the last model request (the as-sent messages + DebugRequestExtras). Called unconditionally from each backend’s capture middleware, independent of the debug sink, so the snapshot is available to /debug-dump on every surface. Overwrites (retains only the most recent call). Callers already guard the invocation; kept trivial so it can never throw.

BaseMessage<MessageStructure<MessageToolSet>, MessageType>[]

DebugRequestExtras

void

GthAbstractAgent.setLastModelRequest


stream(messages, runConfig): Promise<IterableReadableStream<string>>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:634

Induce LLM to stream AI messages with a user message and runnable config. When stream is not appropriate use invoke.

Message[]

RunnableConfig

Promise<IterableReadableStream<string>>

GthAbstractAgent.stream


streamResume(resumeValue, runConfig): Promise<IterableReadableStream<string>>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:649

Resume a graph suspended on a human-in-the-loop interrupt() and stream the continuation as text. Identical plumbing to stream (Esc-to-interrupt, binary handling), except the graph input is a Command({ resume }) instead of fresh messages — so the suspended tool-approval interrupt is answered and the run continues on the same thread.

unknown

RunnableConfig

Promise<IterableReadableStream<string>>

GthAbstractAgent.streamResume


streamWithEvents(messages, runConfig, signal?): AsyncGenerator<AgentStreamEvent>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:875

Stream agent events as typed AgentStreamEvent objects. Yields text deltas, tool call lifecycle events, and tool results.

If a tool with metadata.client === true triggers interrupt(), the underlying graph throws GraphInterrupt; this generator catches it and ends cleanly so the caller’s transport (e.g. AG-UI SSE) can finish the run with the tool call hanging. Resume the suspended graph via streamWithEventsResume on the same thread id.

Message[]

RunnableConfig

AbortSignal

AsyncGenerator<AgentStreamEvent>

GthAbstractAgent.streamWithEvents


streamWithEventsResume(resumeValue, runConfig, queuedMessages?, signal?): AsyncGenerator<AgentStreamEvent>

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:916

Resume a graph that was suspended via interrupt() with the supplied value.

The runnable config must carry the same thread_id used when the graph was suspended (the checkpointer keys state by thread). The resume value is whatever the suspending tool needs back — for frontend-fulfilled tools this is the value the client sends in forwardedProps.command.resume.

unknown

RunnableConfig

BaseMessage<MessageStructure<MessageToolSet>, MessageType>[]

AbortSignal

AsyncGenerator<AgentStreamEvent>

GthAbstractAgent.streamWithEventsResume


protected surfaceRefusal(info): string

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/GthAbstractAgent.ts:517

EXT-37 — surface a detected content-policy refusal: emit the clear, user-facing explanation at WARNING level (an empty-content refusal streams nothing, so without this the console shows nothing) and return the same message so it becomes the turn’s terminal answer. Shared by the non-streaming invoke and streaming streamFromInput paths so both render a refusal identically. A refusal is a successful (if declined) response — never a retry.

RefusalInfo

string

GthAbstractAgent.surfaceRefusal