Skip to main content

Command Palette

Search for a command to run...

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

Published
7 min read
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 tasks

  • gemini-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:

  1. Use lowercase with underscores: customer_support_agent

  2. Be descriptive: data_analysis_agent, math_tutor_agent

  3. Avoid reserved names: user

  4. 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."

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:

  • supportAgent reads billingAgent's description to decide: "Is this a billing question?"

  • billingAgent reads 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 rootAgent so 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 capableTools. 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.