feat(agent): add post-turn stop callback
This commit is contained in:
@@ -215,6 +215,18 @@ async function runLoop(
|
||||
|
||||
await emit({ type: "turn_end", message, toolResults });
|
||||
|
||||
if (
|
||||
await config.shouldStopAfterTurn?.({
|
||||
message,
|
||||
toolResults,
|
||||
context: currentContext,
|
||||
newMessages,
|
||||
})
|
||||
) {
|
||||
await emit({ type: "agent_end", messages: newMessages });
|
||||
return;
|
||||
}
|
||||
|
||||
pendingMessages = (await config.getSteeringMessages?.()) || [];
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +100,18 @@ export interface AfterToolCallContext {
|
||||
context: AgentContext;
|
||||
}
|
||||
|
||||
/** Context passed to `shouldStopAfterTurn`. */
|
||||
export interface ShouldStopAfterTurnContext {
|
||||
/** The assistant message that completed the turn. */
|
||||
message: AssistantMessage;
|
||||
/** Tool result messages passed to the preceding `turn_end` event. */
|
||||
toolResults: ToolResultMessage[];
|
||||
/** Current agent context after the turn's assistant message and tool results have been appended. */
|
||||
context: AgentContext;
|
||||
/** Messages that this loop invocation will return if it exits at this point. Prompt runs include the initial prompt messages; continuation runs do not include pre-existing context messages. */
|
||||
newMessages: AgentMessage[];
|
||||
}
|
||||
|
||||
export interface AgentLoopConfig extends SimpleStreamOptions {
|
||||
model: Model<any>;
|
||||
|
||||
@@ -163,10 +175,22 @@ export interface AgentLoopConfig extends SimpleStreamOptions {
|
||||
*/
|
||||
getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;
|
||||
|
||||
/**
|
||||
* Called after each turn fully completes and `turn_end` has been emitted.
|
||||
*
|
||||
* If it returns true, the loop emits `agent_end` and exits before polling steering or follow-up queues,
|
||||
* without starting another LLM call. The current assistant response and any tool executions finish normally.
|
||||
*
|
||||
* Use this to request a graceful stop after the current turn, e.g. before context gets too full.
|
||||
*
|
||||
* Contract: must not throw or reject. Throwing interrupts the low-level agent loop without producing a normal event sequence.
|
||||
*/
|
||||
shouldStopAfterTurn?: (context: ShouldStopAfterTurnContext) => boolean | Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Returns steering messages to inject into the conversation mid-run.
|
||||
*
|
||||
* Called after the current assistant turn finishes executing its tool calls.
|
||||
* Called after the current assistant turn finishes executing its tool calls, unless `shouldStopAfterTurn` exits first.
|
||||
* If messages are returned, they are added to the context before the next LLM call.
|
||||
* Tool calls from the current assistant message are not skipped.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user