Building Agents with ADK & TypeScript — Part 2: Define Your Agent's Identity

Picking up from Part 1: You built and ran your first ADK agent in TypeScript using
@google/adk. You verified it works via the CLI and the web UI. Now it's time to understand what each part of that agent definition actually does — and how to write it intentionally.
Understanding Your First Agent
In Part 1, you created a working LlmAgent with this code:
export const rootAgent = new LlmAgent({
name: 'hello_time_agent',
model: 'gemini-2.5-flash',
description: 'Tells the current time in a specified city.',
instruction: `You are a helpful assistant that tells the current time in a city.
Use the 'getCurrentTime' tool for this purpose.`,
tools: [getCurrentTime],
});
You verified it works with npx adk web. It's a success.
But what do these parameters actually mean? And how can you customize this agent for specific tasks? Think of this module as understanding the "Model" component from the agent formula in Part 1 — the reasoning brain of your agent.
The Four Core Parameters
Every LlmAgent is defined by four core parameters. Let's explore each one.
1. model (required)
What it is: The underlying large language model (LLM) that powers your agent's reasoning and decision-making.
model: 'gemini-2.5-flash'
What this does
Determines your agent's intelligence and capabilities
Affects cost per request and response speed
Different models have different strengths (speed vs. capability)
Available models
gemini-2.5-flash— Fast, efficient, and great for most tasksgemini-2.5-pro— More capable and better for complex reasoning
Think of it like choosing an engine for your car — a more powerful engine can handle more complex tasks but may cost more to run.
Important: This is a required parameter. Your agent cannot function without specifying a model.
2.name (required)
What it is: A unique string identifier for your agent.
typescriptname: 'hello_time_agent'
What this does:
Identifies your agent internally within ADK Critical in multi-agent systems where agents refer to each other Used for logging, debugging, and agent delegation
Naming conventions:
Use lowercase with underscores: customer_support_agent
Be descriptive: data_analysis_agent, math_tutor_agent
Avoid reserved names: user
Don't use camelCase: use my_agent, not myAgent
From ADK docs: "Every agent needs a unique string identifier. This name is crucial for internal operations, especially in multi-agent systems, where agents need to refer to or delegate tasks to each other."
3. description (optional, but recommended for multi-agent)
What it is: A concise summary of what your agent does.
description: 'Tells the current time in a specified city.'
What this does:
Used by other agents to decide if they should route tasks to this agent
Helps in multi-agent systems where agents delegate to each other
Not used by the agent itself for its own behavior
When to use it:
Building multi-agent systems with delegation
When this agent will be called by other agents
Less critical for single-agent applications
Good descriptions:
"Handles customer billing inquiries and processes payment updates""Analyzes sales data and generates weekly performance reports"
Weak descriptions (too vague):
"Billing agent""Helper"
4. instruction (optional, but critical for behavior)
What it is: The behavioral blueprint that guides how your agent acts and responds.
instruction: `You are a helpful assistant that tells the current time in a city. Use the 'getCurrentTime' tool for this purpose.`
What this does:
Defines the agent's personality and communication style
Specifies the agent's core task or goal
Sets boundaries and constraints on behavior
Guides when and how to use tools
Shapes the output format
From ADK docs: "The instruction parameter is arguably the most critical for shaping an LlmAgent's behavior. It tells the agent its core task or goal, its personality or persona, constraints on its behavior, and how and when to use its tools."
Tips for effective instructions:
Be clear and specific — avoid ambiguity, clearly state the desired actions and outcomes
Use markdown — improve readability for complex instructions using headings, lists, etc.
Provide examples (few-shot) — for complex tasks or specific output formats, include examples
Guide tool use — don't just list tools, explain when and why the agent should use them
description vs instruction — The Key Difference
This is a critical distinction that trips up a lot of people:
| Parameter | Audience | Purpose | Example |
|---|---|---|---|
| description | Other agents | "Should I route this task here?" | "Handles billing inquiries" |
| instruction | This agent | "How should I behave?" | "You are a billing expert who…" |
Here's a concrete multi-agent example
const billingAgent = new LlmAgent({
model: 'gemini-2.5-flash',
name: 'billing_agent',
// OTHER agents read this to decide if they should delegate here
description: 'Handles customer billing inquiries and payment processing.',
// THIS agent reads this to know how to behave
instruction: `You are a billing specialist.
When helping customers:
1. Be empathetic and patient
2. Explain charges clearly
3. Use the billing_lookup tool to check account details
4. Never promise refunds without manager approval
Always maintain a professional, helpful tone.`,
});
const supportAgent = new LlmAgent({
model: 'gemini-2.5-flash',
name: 'support_agent',
description: 'Handles general customer support questions.',
instruction: `You are a customer support agent.
If a question is about billing, transfer to the billing_agent.
Otherwise, help the customer directly.`,
});
In this example:
supportAgentreadsbillingAgent's description to decide: "Is this a billing question?"billingAgentreads its own instruction to know: "How do I handle billing questions?"
The rootAgent Naming Convention
You might have noticed that in Part 1, the exported agent variable is named rootAgent:
export const rootAgent = new LlmAgent({
name: 'hello_time_agent', // Internal ADK name
// ...
});
Why rootAgent?
ADK's developer tools look for an export named rootAgent as the entry point to your agent system. This convention is what allows npx adk run and npx adk web to discover and run your agent.
Can the internal name be different from the export name?
Yes! The name field inside LlmAgent is separate from your TypeScript export name. You can do this:
// Internal ADK name (used for logging, delegation)
const mySpecializedAgent = new LlmAgent({
model: 'gemini-2.5-flash',
name: 'math_tutor_agent', // Used by ADK internally
description: 'Helps students with algebra.',
instruction: 'You are a patient math tutor...',
});
// Export name that ADK tools look for (must be rootAgent)
export const rootAgent = mySpecializedAgent;
Key rule: Always export your main agent as
rootAgentso ADK tools can find it.
Writing Effective Instructions
Instructions guide your agent's behavior and personality. For now, a simple instruction is enough:
instruction: "You are a patient math tutor. Help students with algebra problems."
This basic instruction tells the agent three things:
Its role (math tutor)
Its personality trait (patient)
Its task (help with algebra)
In a future part of this series, we'll go deeper into advanced instruction patterns — including multi-section structures, persona definitions, few-shot examples, and production-ready patterns.
Putting It All Together
Here's the full picture of what each parameter does in a single agent:
export const rootAgent = new LlmAgent({
model: 'gemini-2.5-flash', // The reasoning brain
name: 'time_assistant_agent', // Internal identity (for ADK & multi-agent)
description: 'Tells the current time in any city.', // For OTHER agents to read
instruction: `You are a helpful assistant that tells the current time in a city.
Use the 'getCurrentTime' tool for this purpose.`, // For THIS agent to read
tools: [getCurrentTime], // What the agent can DO (covered in Part 3)
});
What's Next?
Now that you understand what makes an agent who it is, the next part dives into what makes an agent capable — Tools. We'll look at how to write custom FunctionTool implementations, how to connect them to your agent, and how the agent decides when to call them.



