Skip to content

Commit ab13d4f

Browse files
committed
refactor: update onEnd hook to use destructured arguments for improved readability
1 parent 6a6c7e8 commit ab13d4f

File tree

3 files changed

+49
-45
lines changed

3 files changed

+49
-45
lines changed

examples/with-playwright/src/index.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,6 @@ import {
2929
} from "./tools";
3030
import { mistral } from "@ai-sdk/mistral";
3131

32-
// Define the onEnd hook for browser cleanup
33-
const browserCleanupHook: AgentHooks["onEnd"] = async (
34-
_agent: Agent<any>,
35-
_outputOrError: any,
36-
context: OperationContext,
37-
_isError?: boolean,
38-
) => {
39-
console.log(`[${context.operationId}] Operation finished. Cleaning up browser state...`);
40-
// Call the reset function from the handler using the operation context
41-
await resetBrowserStateInternal(context);
42-
};
43-
4432
// Create a specialized agent for browsing
4533
export const browserAgent = new Agent({
4634
name: "Browser Agent",
@@ -49,7 +37,11 @@ export const browserAgent = new Agent({
4937
model: mistral("mistral-large-latest"),
5038

5139
hooks: {
52-
onEnd: browserCleanupHook,
40+
onEnd: async ({ context }) => {
41+
console.log(`[${context.operationId}] Operation finished. Cleaning up browser state...`);
42+
// Call the reset function from the handler using the operation context
43+
await resetBrowserStateInternal(context);
44+
},
5345
},
5446
tools: [
5547
// Navigation tools

website/docs/agents/context.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import {
4646
Agent,
4747
createHooks,
4848
createTool,
49+
type OnEndHookArgs,
4950
type OperationContext,
5051
type ToolExecutionContext,
5152
} from "@voltagent/core";
@@ -69,7 +70,7 @@ async function ensurePage(context: OperationContext): Promise<Page> {
6970

7071
// Hook for cleanup
7172
const hooks = createHooks({
72-
onEnd: async (_agent, _result, context: OperationContext) => {
73+
onEnd: async ({ context }: OnEndHookArgs) => {
7374
const browser = context.userContext.get(BROWSER_KEY) as Browser | undefined;
7475
if (browser) {
7576
console.log(`[${context.operationId}] Closing browser for context...`);
@@ -124,6 +125,8 @@ import {
124125
Agent,
125126
createHooks,
126127
createTool,
128+
type OnStartHookArgs,
129+
type OnEndHookArgs,
127130
type OperationContext,
128131
type ToolExecutionContext,
129132
} from "@voltagent/core";
@@ -133,13 +136,13 @@ import { openai } from "@ai-sdk/openai";
133136

134137
// Define hooks that set and retrieve data
135138
const hooks = createHooks({
136-
onStart: (agent: Agent<any>, context: OperationContext) => {
139+
onStart: ({ agent, context }: OnStartHookArgs) => {
137140
// Set a unique request ID for this operation
138141
const requestId = `req-${Date.now()}`;
139142
context.userContext.set("requestId", requestId);
140143
console.log(`[${agent.name}] Operation started. RequestID: ${requestId}`);
141144
},
142-
onEnd: (agent: Agent<any>, result: any, context: OperationContext) => {
145+
onEnd: ({ agent, context }: OnEndHookArgs) => {
143146
// Retrieve the request ID at the end of the operation
144147
const requestId = context.userContext.get("requestId");
145148
console.log(`[${agent.name}] Operation finished. RequestID: ${requestId}`);
@@ -179,9 +182,3 @@ await agent.generateText(
179182

180183
// Console output will show logs from onStart, the tool (if called), and onEnd,
181184
```
182-
183-
In this example:
184-
185-
1. The `onStart` hook generates a `requestId` and stores it in `userContext`.
186-
2. If the LLM decides to use the `custom_context_logger` tool, the tool's `execute` function accesses the `requestId` from `userContext` via the `options.operationContext` provided to it.
187-
3. The `onEnd` hook retrieves the same `requestId` from the context, demonstrating that the data persisted throughout the operation's lifecycle.

website/docs/agents/overview.md

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -272,41 +272,56 @@ console.log(response.text);
272272

273273
**Why?** To observe and potentially intercept or modify the agent's behavior at various lifecycle stages (start, end, tool calls, etc.) for logging, debugging, or custom logic.
274274

275-
Hooks are triggered at specific points during the execution of `generate*`/`stream*` methods.
275+
Hooks are triggered at specific points during the execution of `generate*`/`stream*` methods. Each hook receives a single argument object containing relevant information like the agent instance and operation context.
276276

277277
```ts
278-
import { Agent, createHooks } from "@voltagent/core";
278+
import {
279+
Agent,
280+
createHooks,
281+
type OnStartHookArgs,
282+
type OnEndHookArgs,
283+
type OnToolStartHookArgs,
284+
type OnToolEndHookArgs,
285+
} from "@voltagent/core";
279286
import { VercelAIProvider } from "@voltagent/vercel-ai";
280287
import { openai } from "@ai-sdk/openai";
281288

282289
const hooks = createHooks({
283290
// Called when any agent interaction starts (generateText, streamText, etc.)
284-
onStart: async (agentInstance) => {
285-
console.log(`Agent ${agentInstance.name} starting interaction...`);
291+
onStart: async ({ agent, context }: OnStartHookArgs) => {
292+
console.log(`Agent ${agent.name} starting interaction... Context:`, context);
286293
},
287-
// Called when the interaction successfully finishes
288-
onEnd: async (agentInstance, result) => {
289-
// Result format depends on the method called (e.g., { text: ..., usage: ... } for generateText)
290-
console.log(
291-
`Agent ${agentInstance.name} finished. Final output:`,
292-
result.text || result.object
293-
);
294+
// Called when the interaction finishes (successfully or with an error)
295+
onEnd: async ({ agent, output, error, context }: OnEndHookArgs) => {
296+
if (error) {
297+
console.error(`Agent ${agent.name} finished with error:`, error);
298+
} else if (output) {
299+
// Output format depends on the method called (e.g., { text: ..., usage: ... } for generateText)
300+
console.log(
301+
`Agent ${agent.name} finished successfully. Final output:`,
302+
output.text ?? output.object // Access 'text' or 'object' based on the operation type
303+
);
304+
}
305+
console.log("Finished context:", context);
294306
},
295307
// Called before a tool is executed
296-
onToolStart: async (agentInstance, toolCall) => {
297-
console.log(`Agent ${agentInstance.name} starting tool: ${toolCall.toolName}`);
298-
},
299-
// Called after a tool finishes execution
300-
onToolEnd: async (agentInstance, toolResult) => {
301-
console.log(
302-
`Agent ${agentInstance.name} finished tool: ${toolResult.toolName}, Result:`,
303-
toolResult.result
304-
);
308+
onToolStart: async ({ agent, tool, context }: OnToolStartHookArgs) => {
309+
console.log(`Agent ${agent.name} starting tool: ${tool.name}. Context:`, context);
305310
},
306-
// Called if an error occurs during the interaction
307-
onError: async (agentInstance, error) => {
308-
console.error(`Agent ${agentInstance.name} encountered an error:`, error);
311+
// Called after a tool finishes execution (successfully or with an error)
312+
onToolEnd: async ({ agent, tool, output, error, context }: OnToolEndHookArgs) => {
313+
if (error) {
314+
console.error(`Agent ${agent.name} failed tool: ${tool.name}. Error:`, error);
315+
} else {
316+
console.log(
317+
`Agent ${agent.name} finished tool: ${tool.name}. Result:`,
318+
output // Tool output is directly available
319+
);
320+
}
321+
console.log("Tool context:", context);
309322
},
323+
// Note: There is no top-level 'onError' hook. Errors are handled within onEnd and onToolEnd.
324+
// The 'onHandoff' hook (not shown here) is called when control is passed between agents (e.g., sub-agents).
310325
});
311326

312327
const agent = new Agent({

0 commit comments

Comments
 (0)