Skip to content

Commit 6521137

Browse files
authored
feat(tarko-agent): add onEachAgentLoopEnd hook (#1111)
1 parent c135aa5 commit 6521137

File tree

4 files changed

+71
-3
lines changed

4 files changed

+71
-3
lines changed

multimodal/tarko/agent-interface/src/agent-instance.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,23 @@ export interface PrepareRequestResult {
164164
/** Modified tools array */
165165
tools: Tool[];
166166
}
167+
168+
/**
169+
* Context provided to the onEachAgentLoopEnd hook
170+
*/
171+
export interface EachAgentLoopEndContext {
172+
/** Session identifier for this conversation */
173+
sessionId: string;
174+
175+
/** Current iteration number (1-based) */
176+
iteration: number;
177+
178+
/** Whether this iteration produced a final answer (no more tool calls) */
179+
hasFinalAnswer: boolean;
180+
181+
/** Whether the loop will continue to next iteration */
182+
willContinue: boolean;
183+
184+
/** The assistant message event from this iteration (if any) */
185+
assistantEvent?: import('./agent-event-stream').AgentEventStream.AssistantMessageEvent;
186+
}

multimodal/tarko/agent-interface/src/agent.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
LoopTerminationCheckResult,
1616
PrepareRequestContext,
1717
PrepareRequestResult,
18+
EachAgentLoopEndContext,
1819
} from './agent-instance';
1920
import { AgentRunObjectOptions, AgentRunStreamingOptions } from './agent-run-options';
2021
import {
@@ -209,6 +210,18 @@ export interface IAgent<T extends AgentOptions = AgentOptions> {
209210
*/
210211
onEachAgentLoopStart(sessionId: string): void | Promise<void>;
211212

213+
/**
214+
* Hook called at the end of each agent loop iteration
215+
*
216+
* This method is invoked after each iteration of the agent loop completes,
217+
* allowing derived classes to perform cleanup, logging, or state updates
218+
* based on the iteration results.
219+
*
220+
* @param context The iteration end context including session info and results
221+
* @returns A promise that resolves when post-iteration cleanup is complete
222+
*/
223+
onEachAgentLoopEnd(context: EachAgentLoopEndContext): void | Promise<void>;
224+
212225
/**
213226
* Hook called at the end of the agent's execution loop
214227
*
@@ -299,4 +312,4 @@ export interface IAgent<T extends AgentOptions = AgentOptions> {
299312
onPrepareRequest(
300313
context: PrepareRequestContext,
301314
): Promise<PrepareRequestResult> | PrepareRequestResult;
302-
}
315+
}

multimodal/tarko/agent/src/agent/base-agent.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
Tool,
1717
PrepareRequestContext,
1818
PrepareRequestResult,
19+
EachAgentLoopEndContext,
1920
} from '@tarko/agent-interface';
2021
import { getLogger } from '@tarko/shared-utils';
2122

@@ -153,6 +154,20 @@ export abstract class BaseAgent<T extends AgentOptions = AgentOptions> {
153154
// Derived classes can override to insert custom logic
154155
}
155156

157+
/**
158+
* Hook called at the end of each agent loop iteration
159+
* This method is invoked after each iteration of the agent loop completes,
160+
* allowing derived classes to perform cleanup, logging, or state updates
161+
* based on the iteration results
162+
*
163+
* @param context The iteration end context including session info and results
164+
* @returns A promise that resolves when post-iteration cleanup is complete
165+
*/
166+
public onEachAgentLoopEnd(context: EachAgentLoopEndContext): void | Promise<void> {
167+
// Default implementation does nothing
168+
// Derived classes can override to insert custom logic
169+
}
170+
156171
/**
157172
* Hook called before a tool is executed
158173
* This allows subclasses to intercept or modify tool calls before execution
@@ -343,4 +358,4 @@ export abstract class BaseAgent<T extends AgentOptions = AgentOptions> {
343358
// Default implementation: return all tools without modification
344359
return tools;
345360
}
346-
}
361+
}

multimodal/tarko/agent/src/agent/runner/loop-executor.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import { AgentEventStream, ToolCallEngine } from '@tarko/agent-interface';
6+
import { AgentEventStream, ToolCallEngine, EachAgentLoopEndContext } from '@tarko/agent-interface';
77
import { getLogger } from '@tarko/shared-utils';
88
import { ResolvedModel } from '@tarko/model-provider';
99
import { LLMProcessor } from './llm-processor';
@@ -152,10 +152,13 @@ export class LoopExecutor {
152152

153153
// Check if we've reached a final answer
154154
const assistantEvents = this.eventStream.getEventsByType(['assistant_message']);
155+
let currentAssistantEvent: AgentEventStream.AssistantMessageEvent | undefined;
156+
155157
if (assistantEvents.length > 0) {
156158
const latestAssistantEvent = assistantEvents[
157159
assistantEvents.length - 1
158160
] as AgentEventStream.AssistantMessageEvent;
161+
currentAssistantEvent = latestAssistantEvent;
159162

160163
if (!latestAssistantEvent.toolCalls || latestAssistantEvent.toolCalls.length === 0) {
161164
finalEvent = latestAssistantEvent;
@@ -165,6 +168,23 @@ export class LoopExecutor {
165168
}
166169
}
167170

171+
// FIXME: Create `iterationEndContext` on demand.
172+
// Call the iteration end hook
173+
try {
174+
const iterationEndContext: EachAgentLoopEndContext = {
175+
sessionId,
176+
iteration,
177+
hasFinalAnswer: finalEvent !== null,
178+
willContinue: finalEvent === null && iteration < this.maxIterations - 1,
179+
assistantEvent: currentAssistantEvent,
180+
};
181+
182+
await Promise.resolve(this.agent.onEachAgentLoopEnd(iterationEndContext));
183+
this.logger.debug(`[Agent] Post-iteration hook executed for iteration ${iteration}`);
184+
} catch (error) {
185+
this.logger.error(`[Agent] Error in post-iteration hook: ${error}`);
186+
}
187+
168188
this.logger.info(`[Iteration] ${iteration}/${this.maxIterations} completed`);
169189
}
170190

0 commit comments

Comments
 (0)