runConversation
runConversation(
source,_preamble,userMessages,config,resolvers?,command?,agentFactory?):Promise<ConversationTurnResult[]>
Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/runtime/conversation.ts:78
Run a scripted MULTI-TURN conversation and return one ConversationTurnResult per turn.
This is the conversational counterpart to ../runtime/singleShot.js runSingleShot (which is stateless — a fresh agent per call). It builds the agent + resolves tools ONCE, then runs each turn against the ACCUMULATED message history so cross-turn “memory” / identity behaviour is real, and cleans up ONCE at the end (reusing runSingleShot’s cleanup discipline — the resolvers are the caller’s to tear down, exactly as with runSingleShot).
History mechanism = stateless replay of the growing message array. Messages accumulate as
[user1, ai1, user2, ai2, …]: per turn a HumanMessage(user) is appended, the agent runs on the
WHOLE array, and its answer is appended as an AIMessage so the next turn sees it. The system
prompt is NOT seeded here — the agent composes it via createAgent({ systemPrompt }) (BATCH-13;
see runSingleShot), so the replayed array carries only human/assistant turns. Before each
turn the runner’s thread is rotated (GthAgentRunner.resetThread) so the checkpointer starts
empty and the replayed array is the sole history (no add_messages double-append). This mirrors
the AG-UI server’s “client is the source of truth for history — it sends the full message list
every turn” model and reuses the existing processMessages + resetThread machinery with no new
agent surface. Known limitation (unverified pending a live pass): replay carries prior
answers (as AIMessage text) but NOT prior tool-call / tool-result messages — a checkpointer-
thread approach (send only the new message, let add_messages accumulate) would preserve those.
Per-turn tool capture (GS2-16): processMessages resets the analytics tally at its top, so
getRunStats() read right after each turn returns THAT turn’s tool/token delta (not cumulative).
A turn that fails is recorded (ok:false, error) and the conversation STOPS (later turns depend
on the broken context), so the returned array may be shorter than userMessages — the caller
(gth eval’s runner) fails the un-run turns.
Parameters
Section titled “Parameters”source
Section titled “source”string
The source label (used for output/session-file naming), e.g. EVAL-<cellId>.
_preamble
Section titled “_preamble”string
Deprecated/ignored (BATCH-13): the agent composes the system prompt itself (via
createAgent({ systemPrompt })); seeding it here too produced a second system message that
@langchain/anthropic rejects. Retained positionally so existing callers need no change.
userMessages
Section titled “userMessages”string[]
The ordered user turns to send (one conversation).
config
Section titled “config”The resolved config.
resolvers?
Section titled “resolvers?”Optional agent resolvers (tools/middleware); the caller owns their cleanup.
command?
Section titled “command?”GthCommand = 'ask'
The originating command (defaults to ask); selects the agent mode prompt.
agentFactory?
Section titled “agentFactory?”Optional backend factory (B5); omitted = the runner’s lean default.
Returns
Section titled “Returns”Promise<ConversationTurnResult[]>
One ConversationTurnResult per turn attempted, in turn order.