diff --git a/docs/tools/function-tools.md b/docs/tools/function-tools.md index f466e828e..f47b837ae 100644 --- a/docs/tools/function-tools.md +++ b/docs/tools/function-tools.md @@ -144,6 +144,20 @@ A tool can write data to a `temp:` variable, and a subsequent tool can read it. For input `GOOG`: {"symbol": "GOOG", "price": "1.0"} ``` + === "Typescript" + + This tool retrieves the mocked value of a stock price. + + ```typescript + --8<-- "examples/typescript/snippets/tools/function-tools/function-tools-example.ts" + ``` + + The return value from this tool will be an object. + + ```json + For input `GOOG`: {"price": 2800.0, "currency": "USD"} + ``` + ### Best Practices While you have considerable flexibility in defining your function, remember that simplicity enhances usability for the LLM. Consider these guidelines: @@ -327,6 +341,12 @@ To use an agent as a tool, wrap the agent with the AgentTool class. AgentTool.create(agent) ``` +=== "TypeScript" + + ```typescript + tools: [new AgentTool({agent: agentB})] + ``` + ### Customization The `AgentTool` class provides the following attributes for customizing its behavior: @@ -347,6 +367,12 @@ The `AgentTool` class provides the following attributes for customizing its beha --8<-- "examples/java/snippets/src/main/java/tools/AgentToolCustomization.java:full_code" ``` + === "TypeScript" + + ```typescript + --8<-- "examples/typescript/snippets/tools/function-tools/agent-as-a-tool-example.ts" + ``` + ### How it works 1. When the `main_agent` receives the long text, its instruction tells it to use the 'summarize' tool for long texts. diff --git a/examples/typescript/.gitignore b/examples/typescript/.gitignore new file mode 100644 index 000000000..968654180 --- /dev/null +++ b/examples/typescript/.gitignore @@ -0,0 +1 @@ +**/package-lock.json diff --git a/examples/typescript/snippets/tools/function-tools/agent-as-a-tool-example.ts b/examples/typescript/snippets/tools/function-tools/agent-as-a-tool-example.ts new file mode 100644 index 000000000..060e87a09 --- /dev/null +++ b/examples/typescript/snippets/tools/function-tools/agent-as-a-tool-example.ts @@ -0,0 +1,73 @@ +import { + AgentTool, + InMemoryRunner, + LlmAgent, +} from '@google/adk'; +import {Part} from '@google/genai'; + +/** + * This example demonstrates how to use an agent as a tool. + */ +async function main() { + // Define the summarization agent that will be used as a tool + const summaryAgent = new LlmAgent({ + name: 'summary_agent', + model: 'gemini-2.5-flash', + description: 'Agent to summarize text', + instruction: + 'You are an expert summarizer. Please read the following text and provide a concise summary.', + }); + + // Define the main agent that uses the summarization agent as a tool. + // skipSummarization is set to true, so the main_agent will directly output + // the result from the summary_agent without further processing. + const mainAgent = new LlmAgent({ + name: 'main_agent', + model: 'gemini-2.5-flash', + instruction: + "You are a helpful assistant. When the user provides a text, use the 'summary_agent' tool to generate a summary. Always forward the user's message exactly as received to the 'summary_agent' tool, without modifying or summarizing it yourself. Present the response from the tool to the user.", + tools: [new AgentTool({agent: summaryAgent, skipSummarization: true})], + }); + + const appName = 'agent-as-a-tool-app'; + const runner = new InMemoryRunner({agent: mainAgent, appName}); + + const longText = `Quantum computing represents a fundamentally different approach to computation, +leveraging the bizarre principles of quantum mechanics to process information. Unlike classical computers +that rely on bits representing either 0 or 1, quantum computers use qubits which can exist in a state of superposition - effectively +being 0, 1, or a combination of both simultaneously. Furthermore, qubits can become entangled, +meaning their fates are intertwined regardless of distance, allowing for complex correlations. This parallelism and +interconnectedness grant quantum computers the potential to solve specific types of incredibly complex problems - such +as drug discovery, materials science, complex system optimization, and breaking certain types of cryptography - far +faster than even the most powerful classical supercomputers could ever achieve, although the technology is still largely in its developmental stages.`; + + // Create the session before running the agent + await runner.sessionService.createSession({ + appName, + userId: 'user1', + sessionId: 'session1', + }); + + // Run the agent with the long text to summarize + const events = runner.run({ + userId: 'user1', + sessionId: 'session1', + newMessage: { + role: 'user', + parts: [{text: longText}], + }, + }); + + // Print the final response from the agent + console.log('Agent Response:'); + for await (const event of events) { + if (event.content?.parts) { + const responsePart = event.content.parts.find((p: Part) => p.functionResponse); + if (responsePart && responsePart.functionResponse) { + console.log(responsePart.functionResponse.response); + } + } + } +} + +main(); \ No newline at end of file diff --git a/examples/typescript/snippets/tools/function-tools/function-tools-example.ts b/examples/typescript/snippets/tools/function-tools/function-tools-example.ts new file mode 100644 index 000000000..9aabe06e3 --- /dev/null +++ b/examples/typescript/snippets/tools/function-tools/function-tools-example.ts @@ -0,0 +1,71 @@ +import {Content, Part} from '@google/genai'; +import { + FunctionTool, + InMemoryRunner, + LlmAgent, +} from '@google/adk'; +import {z} from 'zod'; + +// Define the function to get the stock price +async function getStockPrice({ticker}: {ticker: string}): Promise> { + console.log(`Getting stock price for ${ticker}`); + // In a real-world scenario, you would fetch the stock price from an API + const price = (Math.random() * 1000).toFixed(2); + return {price: `$${price}`}; +} + +async function main() { + // Define the schema for the tool's parameters using Zod + const getStockPriceSchema = z.object({ + ticker: z.string().describe('The stock ticker symbol to look up.'), + }); + + // Create a FunctionTool from the function and schema + const stockPriceTool = new FunctionTool({ + name: 'getStockPrice', + description: 'Gets the current price of a stock.', + parameters: getStockPriceSchema, + execute: getStockPrice, + }); + + // Define the agent that will use the tool + const stockAgent = new LlmAgent({ + name: 'stock_agent', + model: 'gemini-2.5-flash', + instruction: 'You can get the stock price of a company.', + tools: [stockPriceTool], + }); + + // Create a runner for the agent + const runner = new InMemoryRunner({agent: stockAgent}); + + // Create a new session + const session = await runner.sessionService.createSession({ + appName: runner.appName, + userId: 'test-user', + }); + + const userContent: Content = { + role: 'user', + parts: [{text: 'What is the stock price of GOOG?'},], + }; + + // Run the agent and get the response + const response = []; + for await (const event of runner.run({ + userId: session.userId, + sessionId: session.id, + newMessage: userContent, + })) { + response.push(event); + } + + // Print the final response from the agent + const finalResponse = response[response.length - 1]; + if (finalResponse?.content?.parts) { + console.log(finalResponse.content.parts.map((part: Part) => part.text).join('')); + } +} + +main(); + diff --git a/examples/typescript/snippets/tools/function-tools/package.json b/examples/typescript/snippets/tools/function-tools/package.json new file mode 100644 index 000000000..425a7437f --- /dev/null +++ b/examples/typescript/snippets/tools/function-tools/package.json @@ -0,0 +1,18 @@ +{ + "name": "adk-function-tools-ts-example", + "version": "1.0.0", + "description": "ADK TS example for function tools.", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "Apache-2.0", + "type": "commonjs", + "dependencies": { + "@google/adk": "file:../../../../../../adk-js/core", + "@google/genai": "^1.16.0", + "@opentelemetry/api": "^1.9.0", + "ts-node": "^10.9.2", + "zod": "^3.25.76" + } +} \ No newline at end of file diff --git a/examples/typescript/snippets/tools/function-tools/tsconfig.json b/examples/typescript/snippets/tools/function-tools/tsconfig.json new file mode 100644 index 000000000..18eec9992 --- /dev/null +++ b/examples/typescript/snippets/tools/function-tools/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2020", + "moduleResolution": "node", + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "baseUrl": ".", + "paths": { + "@google/adk": ["../../../../../../adk-js/core/src"] + } + } +} \ No newline at end of file