.agents/skills/google-adk-typescript/SKILL.md
Build production-ready AI agents in TypeScript using Google Agent Development Kit (ADK). Use when creating agentic TypeScript/JavaScript applications with LlmAgent, workflow agents (SequentialAgent, ParallelAgent, LoopAgent), custom agents (BaseAgent with runAsyncImpl), FunctionTool with Zod schemas, MCP and OpenAPI tools, multi-agent orchestration, session and state management (outputKey, app/user/temp prefixes, CallbackContext), callbacks and guardrails, testing and evaluation, backend frameworks (Express, Hono), or deploying to Cloud Run or containers. Triggers on "build an agent TypeScript", "ADK TypeScript", "ADK TS", "@google/adk", "multi-agent system TypeScript", "agentic application TypeScript", "Gemini agent TypeScript".
npx skillsauth add szeyu/open-ssyok-finance google-adk-typescriptInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
ADK is Google's open-source, code-first TypeScript framework for building, evaluating, and deploying AI agents. Optimized for Gemini but model-agnostic. Requires Node.js 20.12.7+.
mkdir my-agent && cd my-agent
npm init -y
npm install @google/adk
npm install @google/adk-devtools
npm install -D typescript
npm install zod
npx tsc --init
Project structure:
my-agent/
├── agent.ts
├── package.json
├── tsconfig.json
└── .env
tsconfig.json:
{
"compilerOptions": {
"verbatimModuleSyntax": false
}
}
.env:
GOOGLE_GENAI_API_KEY=your_api_key
# Or use GEMINI_API_KEY=your_api_key (also supported)
# Or for Vertex AI:
# GOOGLE_GENAI_USE_VERTEXAI=TRUE
# GOOGLE_CLOUD_PROJECT=your_project
# GOOGLE_CLOUD_LOCATION=us-central1
Minimal agent (agent.ts):
import { LlmAgent } from '@google/adk';
export const rootAgent = new LlmAgent({
name: 'assistant',
model: 'gemini-2.5-flash',
instruction: 'You are a helpful assistant.',
description: 'A general-purpose assistant.',
});
Run:
npx @google/adk-devtools run agent.ts # CLI
npx @google/adk-devtools web # Dev UI at localhost:8000
| Type | Import | Use When |
|------|--------|----------|
| LlmAgent | @google/adk | Flexible reasoning, tool selection |
| SequentialAgent | @google/adk | Ordered multi-step pipelines |
| ParallelAgent | @google/adk | Concurrent independent tasks |
| LoopAgent | @google/adk | Iterative refinement |
| BaseAgent | @google/adk | Custom orchestration logic |
See references/agents.md for detailed patterns and code examples.
Define tools with FunctionTool and Zod schemas:
import { FunctionTool, LlmAgent } from '@google/adk';
import { z } from 'zod';
const getWeather = new FunctionTool({
name: 'get_weather',
description: 'Get weather for a city.',
parameters: z.object({
city: z.string().describe('City name'),
}),
execute: async ({ city }) => {
return { city, temp: '72F', condition: 'sunny' };
},
});
export const rootAgent = new LlmAgent({
name: 'weather_agent',
model: 'gemini-2.5-flash',
instruction: 'Help users check weather.',
tools: [getWeather],
});
See references/tools.md for MCP, OpenAPI, LongRunningFunctionTool, and built-in tools.
Six core patterns:
outputKey state passingmaxIterationsSee references/multi-agent.md for implementation details.
// 1. outputKey - auto-save agent response to state
const writer = new LlmAgent({
name: 'writer',
outputKey: 'draft', // state['draft'] = agent response
// ...
});
// 2. Instruction templating - read from state
const editor = new LlmAgent({
instruction: 'Edit this draft: {draft}',
// ...
});
// 3. CallbackContext - manual read/write
function myCallback(context: CallbackContext) {
const count = context.state.get('counter', 0);
context.state.set('counter', count + 1);
context.state.set('temp:scratch', 'temporary');
}
State prefixes: unprefixed (session), user: (cross-session per user), app: (global), temp: (discarded after invocation).
const agent = new LlmAgent({
name: 'safe_agent',
beforeAgentCallback: checkIfAgentShouldRun,
afterAgentCallback: modifyOutputAfterAgent,
beforeModelCallback: simpleBeforeModelModifier,
// Also: afterModelCallback, beforeToolCallback, afterToolCallback
});
Return undefined to proceed, return a Content/LlmResponse object to override. See references/callbacks.md.
import { InMemoryRunner } from '@google/adk';
import { createUserContent } from '@google/genai';
const runner = new InMemoryRunner({ agent: rootAgent });
const session = await runner.sessionService.createSession({
appName: runner.appName,
userId: 'user-1',
state: { initial_key: 'value' },
});
for await (const event of runner.runAsync({
userId: session.userId,
sessionId: session.id,
newMessage: createUserContent('Hello'),
})) {
console.log(event);
}
Note: createUserContent and the Content type come from @google/genai (transitive dependency of @google/adk), not from @google/adk directly.
ADK provides trajectory-based evaluation comparing actual agent behavior against expected tool call sequences and reference responses. A recommended best practice is to follow a task-first approach:
Built-in metrics: tool_trajectory_avg_score, response_match_score, final_response_match_v2, rubric_based_final_response_quality_v1, rubric_based_tool_use_quality_v1, hallucinations_v1, safety_v1
Run: npx adk eval <agent_folder> <test_file.test.json>
See references/testing.md for task-first strategy, rubric construction, mocked unit tests, integration tests, and simulated scenario tests.
import express from 'express';
import { InMemoryRunner, isFinalResponse, stringifyContent } from '@google/adk';
import { createUserContent } from '@google/genai';
const app = express();
app.use(express.json());
const runner = new InMemoryRunner({ agent: rootAgent });
app.post('/chat', async (req, res) => {
const { message, sessionId, userId } = req.body;
// Get or create session
let session = await runner.sessionService.getSession({
appName: runner.appName, userId, sessionId,
});
if (!session) {
session = await runner.sessionService.createSession({
appName: runner.appName, userId,
});
}
const events = [];
for await (const event of runner.runAsync({
userId, sessionId: session.id,
newMessage: createUserContent(message),
})) {
if (isFinalResponse(event)) {
events.push({ type: 'response', content: stringifyContent(event) });
}
}
res.json({ events });
});
app.listen(8080);
See references/deployment.md for Hono, Cloud Run, and container patterns.
.describe() for LLM hintsoutputKey - Auto-store agent output in state for downstream agentsdescription fields - Guides LLM routing to sub-agentsasync* generators - Use runAsyncImpl for custom agent flow controlnpx @google/adk-devtools web to inspect events/stateverbatimModuleSyntax: false in tsconfig - causes import errorsCallbackContext.state or outputKey.describe() - LLM gets no hint about parameter purposefor await with runAsyncdocumentation
Create organized, visual study notes with folder structures, diagrams, and example-based learning from source materials (PDFs, lecture notes, documentation). Use when creating structured learning materials, exam preparation notes, or educational documentation. Triggers - organize study notes, create visual learning materials, generate notes with diagrams, exam prep notes, example-based learning.
development
Create and present web-based slides for developers using Markdown, Vue components, code highlighting, animations, and interactive features. Use when building technical presentations, conference talks, or teaching materials.
development
Add smooth slide transitions in Slidev. Use this skill for fade, slide, and custom transitions between slides.
development
Use and customize Slidev themes. Use this skill to apply themes, configure theme options, and create custom themes.