Skip to content

Commit 243e10c

Browse files
docs: add pre/post processing docs for ADK JS (#2424)
## Description Tested on local changes. Latest successful run: https://pantheon.corp.google.com/cloud-build/builds;region=global/740d6aca-271b-4c0b-8584-40cae58950c8?e=13802955&mods=-autopush_coliseum&project=toolbox-testing-438616 ## PR Checklist > Thank you for opening a Pull Request! Before submitting your PR, there are a > few things you can do to make sure it goes smoothly: - [ ] Make sure you reviewed [CONTRIBUTING.md](https://github.com/googleapis/genai-toolbox/blob/main/CONTRIBUTING.md) - [ ] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/genai-toolbox/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) - [ ] Make sure to add `!` if this involve a breaking change 🛠️ Fixes #<issue_number_goes_here> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent fe35e55 commit 243e10c

4 files changed

Lines changed: 3857 additions & 2 deletions

File tree

docs/en/samples/pre_post_processing/js.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,18 @@ This guide demonstrates how to implement these patterns in your Toolbox applicat
1616

1717
{{< tabpane persist=header >}}
1818
{{% tab header="ADK" text=true %}}
19-
Coming soon.
19+
The following example demonstrates how to use the `beforeToolCallback` and `afterToolCallback` hooks in the ADK `LlmAgent` to implement pre and post processing logic.
20+
21+
```js
22+
{{< include "js/adk/agent.js" >}}
23+
```
24+
25+
You can also add model-level (`beforeModelCallback`, `afterModelCallback`) and agent-level (`beforeAgentCallback`, `afterAgentCallback`) hooks to intercept messages at different stages of the execution loop.
26+
27+
For more information, see the [ADK Callbacks documentation](https://google.github.io/adk-docs/callbacks/types-of-callbacks/).
2028
{{% /tab %}}
2129
{{% tab header="Langchain" text=true %}}
22-
The following example demonstrates how to use `ToolboxClient` with LangChain's middleware to implement pre- and post- processing for tool calls.
30+
The following example demonstrates how to use `ToolboxClient` with LangChain's middleware to implement pre and post processing for tool calls.
2331

2432
```js
2533
{{< include "js/langchain/agent.js" >}}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { InMemoryRunner, LlmAgent, LogLevel } from '@google/adk';
2+
import { ToolboxClient } from '@toolbox-sdk/adk';
3+
4+
process.env.GOOGLE_GENAI_API_KEY = process.env.GOOGLE_API_KEY || 'your-api-key'; // Replace it with your API key
5+
6+
const systemPrompt = `
7+
You're a helpful hotel assistant. You handle hotel searching, booking and
8+
cancellations. When the user searches for a hotel, mention it's name, id,
9+
location and price tier. Always mention hotel ids while performing any
10+
searches. This is very important for any operations. For any bookings or
11+
cancellations, please provide the appropriate confirmation. Be sure to
12+
update checkin or checkout dates if mentioned by the user.
13+
Don't ask for confirmations from the user.
14+
`;
15+
16+
// Pre-Processing
17+
function enforeBusinessRules({tool, args}) {
18+
const name = tool.name;
19+
console.log(`POLICY CHECK: Intercepting '${name}'`);
20+
21+
if (name === "update-hotel" && args.checkin_date && args.checkout_date) {
22+
try {
23+
const start = new Date(args.checkin_date);
24+
const end = new Date(args.checkout_date);
25+
const duration = (end - start) / (1000 * 60 * 60 * 24); // days
26+
27+
if (duration > 14) {
28+
console.log("BLOCKED: Stay too long");
29+
return "Error: Maximum stay duration is 14 days.";
30+
}
31+
} catch (e) {
32+
// Ignore invalid dates
33+
}
34+
}
35+
return undefined;
36+
}
37+
38+
// Post-Processing
39+
function enrichResponse({tool, response}) {
40+
const name = tool.name;
41+
console.log(`ENRICHING RESPONSE: Intercepting '${name}'`);
42+
if (name === "book-hotel") {
43+
let content = response;
44+
if (response && typeof response === "object") {
45+
content = response.content;
46+
}
47+
if (typeof content === "string" && !content.includes("Error")) {
48+
const loyaltyBonus = 500;
49+
const enrichedContent = `Booking Confirmed!\n You earned ${loyaltyBonus} Loyalty Points with this stay.\n\nSystem Details: ${content}`;
50+
51+
if (response && typeof response === "object") {
52+
return { ...response, content: enrichedContent };
53+
}
54+
return enrichedContent;
55+
}
56+
}
57+
return response;
58+
}
59+
60+
async function runTurn(runner, userId, sessionId, prompt) {
61+
console.log(`\nUSER: '${prompt}'`);
62+
const content = { role: 'user', parts: [{ text: prompt }] };
63+
const stream = runner.runAsync({ userId, sessionId, newMessage: content });
64+
65+
let fullText = "";
66+
for await (const chunk of stream) {
67+
if (chunk.content && chunk.content.parts) {
68+
fullText += chunk.content.parts.map(p => p.text || "").join("");
69+
}
70+
}
71+
72+
console.log("-".repeat(50));
73+
console.log(`AI: ${fullText}`);
74+
}
75+
76+
export async function main() {
77+
const userId = 'test_user';
78+
const client = new ToolboxClient('http://127.0.0.1:5000');
79+
const tools = await client.loadToolset("my-toolset");
80+
81+
const rootAgent = new LlmAgent({
82+
name: 'hotel_agent',
83+
model: 'gemini-2.5-flash',
84+
description: 'Agent for hotel bookings and administration.',
85+
instruction: systemPrompt,
86+
tools: tools,
87+
// Add any pre- and post- processing callbacks
88+
beforeToolCallback: enforeBusinessRules,
89+
afterToolCallback: enrichResponse
90+
});
91+
92+
const appName = rootAgent.name;
93+
const runner = new InMemoryRunner({ agent: rootAgent, appName, logLevel: LogLevel.ERROR });
94+
const session = await runner.sessionService.createSession({ appName, userId });
95+
96+
// Turn 1: Booking
97+
await runTurn(runner, userId, session.id, "Book hotel with id 3.");
98+
99+
// Turn 2: Policy Violation
100+
await runTurn(runner, userId, session.id, "Update my hotel with id 3 with checkin date 2025-01-18 and checkout date 2025-02-10");
101+
}
102+
103+
main();

0 commit comments

Comments
 (0)