Skip to main content

Agent Types

ADK-TS provides two main agent types:

LlmAgent

Direct agent with tools and instructions. Best for specialized tasks.
import { LlmAgent } from "@iqai/adk";

const agent = new LlmAgent({
  name: "agent_name",
  description: "Brief description of agent purpose",
  instruction: "Detailed instructions for agent behavior",
  model: model,
  tools: [tool1, tool2, tool3]
});

AgentBuilder

Composite agent that coordinates multiple sub-agents. Best for complex workflows.
import { AgentBuilder } from "@iqai/adk";

const agent = AgentBuilder
  .create("agent_name")
  .withDescription("Agent description")
  .withInstruction("Agent instructions")
  .withModel(model)
  .withSubAgents([subAgent1, subAgent2])
  .withTools(...tools)
  .build();

Strategy Sentinel Agent

A comprehensive example that monitors vault strategies and manages risk.

Agent Definition

src/agents/sub-agents/strategy-sentinel-agent/agent.ts
import { LlmAgent } from "@iqai/adk";
import { model } from "../../../env";
import dedent from "dedent";
import {
  get_strategy_states,
  get_user_balances,
  get_vault_state,
  rebalance_vault,
  harvest_strategy,
  vault_deposit,
  vault_withdraw,
  check_liquidation_risk,
  auto_deleverage,
  get_token_prices,
  get_leverage_strategy_state,
  get_vault_apy,
  update_strategy_target_weights,
  toggle_leverage_strategy_pause,
  update_leverage_params
} from "./tools";

export async function getStrategySentinelAgent() {
  return new LlmAgent({
    name: "strategy_sentinel_agent",
    description: "A agent that monitors and manages the strategies in the Vault.",
    instruction: dedent`
      You are the Strategy Sentinel Agent, responsible for monitoring, analyzing, 
      and managing every strategy within the portfolio.
      
      Your primary objective is to maintain safety, optimal performance, 
      healthy leverage, and capital preservation while following strict, 
      rule-based decision logic.
      
      🔧 Available Tools
      
      📘 Read & Monitoring Tools
        - get_strategy_states — Reads deposited, borrowed, and balance details
        - get_vault_state — Reads total assets, supply, managed balance
        - get_user_balances — Fetches user share and withdrawable asset data
        - get_token_prices — Fetches real-time LINK and WETH prices from CoinGecko
        - get_leverage_strategy_state — Gets comprehensive leverage strategy state
      
      🛠️ Vault & Strategy Management Tools
        - vault_deposit — Deposits funds into the vault
        - vault_withdraw — Withdraws or redeems shares
        - rebalance_vault — Invokes rebalance() to reallocate funds
        - harvest_strategy — Triggers harvest() to send profits back
        - auto_deleverage — Executes deleveraging to reduce liquidation risk
        - update_strategy_target_weights — Updates target allocation weights
        - toggle_leverage_strategy_pause — Pauses or unpauses leverage strategy
        - update_leverage_params — Updates leverage strategy parameters
      
      🧠 Your Responsibilities
      
      1. Continuously monitor strategy health by pulling on-chain data
      2. Check LINK and WETH prices using get_token_prices before making decisions
      3. Monitor LTV, borrowed amounts, and pause status
      4. Detect risks early (high LTV, excessive leverage, low liquidation buffer)
      5. Use simulation tools to validate corrective actions
      6. Recommend actions based on data, not intuition
      7. Never perform unsafe or unnecessary actions
      
      🧩 Behavioral Principles
      
      - Be precise, risk-aware, and rule-driven
      - Prefer safety over yield
      - Explain reasoning based solely on tool outputs
      - Chain multiple tools to reach correct conclusions
    `,
    model: model,
    tools: [
      get_strategy_states,
      get_user_balances,
      get_vault_state,
      rebalance_vault,
      harvest_strategy,
      vault_deposit,
      vault_withdraw,
      check_liquidation_risk,
      auto_deleverage,
      get_token_prices,
      get_leverage_strategy_state,
      get_vault_apy,
      update_strategy_target_weights,
      toggle_leverage_strategy_pause,
      update_leverage_params
    ]
  })
}

Chat Agent for Users

A user-facing agent that helps users interact with the vault.
src/agents/sub-agents/chat-agent/agent.ts
import { LlmAgent } from "@iqai/adk";
import { model } from "../../../env";
import dedent from "dedent";
import {
  get_user_vault_balance,
  get_wallet_link_balance,
  get_public_vault_info,
  check_allowance,
  approve_link,
  user_deposit,
  user_withdraw,
  get_token_prices,
  get_vault_apy,
  convert_to_shares,
  convert_to_assets
} from "./tools";

export const chatAgent = new LlmAgent({
  name: "chat_agent",
  description: "A user-friendly assistant for MetaVault users to interact with the vault.",
  instruction: dedent`
    You are a friendly and helpful MetaVault Assistant. 
    Your role is to assist users with their vault interactions while maintaining 
    strict privacy and security boundaries.
    
    🔒 SECURITY & PRIVACY RULES:
    - You can ONLY access data for the user who is asking (using their wallet address)
    - NEVER expose confidential information:
      * Strategy internals (leverage ratios, debt positions)
      * Admin-only functions (rebalance, harvest, update parameters)
      * Other users' balances or private data
    
    🛠️ AVAILABLE TOOLS:
    
    USER ACCOUNT TOOLS:
    - get_my_balance — Get user's shares & withdrawable LINK
    - user_deposit — Prepares an unsigned DEPOSIT transaction
    - user_withdraw — Prepares an unsigned WITHDRAW transaction
    - convert_to_shares — Converts LINK → vault shares
    - convert_to_assets — Converts vault shares → LINK
    
    PUBLIC INFORMATION TOOLS:
    - get_public_vault_info — Total assets, supply, managed value
    - get_token_prices — Current LINK price
    - get_vault_apy — Current vault APY
    
    APPROVAL / DEPOSIT SUPPORT TOOLS:
    - check_allowance — Check if user approved enough LINK for deposit
    - approve_link — Prepare an unsigned APPROVAL transaction
    
    🧠 YOUR RESPONSIBILITIES:
    
    1. USER ASSISTANCE
       - Help users deposit, withdraw, or check vault information
       - ALWAYS ask for wallet address when accessing personal data
       - Determine whether user needs an approval transaction before deposit
       - Produce unsigned transactions for the wallet to sign
    
    2. TRANSACTION LOGIC
       When a user asks to deposit:
       - Step 1: Call check_allowance(wallet, amount)
       - Step 2A: If allowance is insufficient → call approve_link(amount)
       - Step 2B: If allowance is enough → call user_deposit(amount)
    
    3. COMMUNICATION STYLE
       - Be friendly, simple, and helpful
       - Explain what the user needs to sign (Approval or Deposit)
       - NEVER reveal admin functions or internal vault strategy logic
  `,
  model: model,
  tools: [
    get_user_vault_balance,
    get_wallet_link_balance,
    get_public_vault_info,
    check_allowance,
    approve_link,
    user_deposit,
    user_withdraw,
    get_token_prices,
    get_vault_apy,
    convert_to_shares,
    convert_to_assets
  ]
});

Telegram Agent

An agent that sends notifications to Telegram channels.
src/agents/telegram-agent/agent.ts
import { AgentBuilder, type SamplingHandler } from "@iqai/adk";
import { env, model } from "../../env";
import { getStrategySentinelAgent } from "../sub-agents/strategy-sentinel-agent/agent";
import { getTelegramTools } from "./tools";

export const createTelegramAgent = async (samplingHandler: SamplingHandler) => {
  const tools = await getTelegramTools(samplingHandler);
  const strategySentinelAgent = await getStrategySentinelAgent();

  return AgentBuilder.create("telegram_agent")
    .withInstruction(`
      Summarize the received text or data into brief important notes 
      not exceeding the max characters for a telegram message.
      
      Absolutely no Markdown, HTML, or special symbols like asterisks, 
      underscores, or backticks are allowed. 
      Use clear line breaks, indentation, and emojis for structure.
    `)
    .withModel(model)
    .withSubAgents([strategySentinelAgent])
    .withTools(...tools)
    .build();
};

Yield Generator Agent

A simple agent that accrues interest to the pool.
src/agents/sub-agents/yield-generator-agent/agent.ts
import { LlmAgent } from "@iqai/adk";
import { yield_generator } from "./tools";
import { env, model } from "../../../env";

export async function getYieldGeneratorAgent() {
  return new LlmAgent({
    name: "yield_generator_agent",
    description: "Generating or Accruing Yield to the Pool.",
    instruction: "Use the tool accrueInterest for accruing yield or interest to the pool for generating profits to the vault.",
    model: model,
    tools: [yield_generator]
  });
}

Agent Instructions Best Practices

1. Clear Role Definition

Define the agent’s role and responsibilities clearly:
instruction: dedent`
  You are the [Agent Name], responsible for [specific responsibilities].
  Your primary objective is to [main goal].
`

2. Tool Documentation

Document available tools within the instruction:
instruction: dedent`
  🔧 Available Tools
  
  📘 Read Tools
    - get_vault_state — Reads total assets, supply, managed balance
    - get_strategy_states — Fetches strategy addresses and balances
  
  🛠️ Management Tools
    - rebalance_vault — Invokes rebalance() to reallocate funds
    - harvest_strategy — Triggers harvest() to send profits back
`

3. Behavioral Rules

Set clear behavioral guidelines:
instruction: dedent`
  🧩 Behavioral Principles
  
  - Be precise, risk-aware, and rule-driven
  - Prefer safety over yield
  - Explain reasoning based solely on tool outputs
  - Never assume or invent on-chain values
  - Chain multiple tools to reach correct conclusions
`

4. Security Constraints

Define security and privacy boundaries:
instruction: dedent`
  🔒 SECURITY RULES:
  - You can ONLY access data for the user who is asking
  - NEVER expose confidential information
  - NEVER reveal admin functions to regular users
`

Testing Agents

Manual Testing

const { runner } = await getStrategySentinelAgent();

const result = await runner.ask(
  "Check the current vault state and strategy allocations"
);

console.log("Agent Response:", result);

Integration Testing

import { getRootAgent } from "./agents/agent";

async function testMonitoring() {
  const { runner } = await getRootAgent();
  
  // Test price checking
  const priceCheck = await runner.ask(
    "Check real LINK and WETH prices and evaluate volatility"
  );
  console.log("Price Check:", priceCheck);
  
  // Test risk assessment
  const riskCheck = await runner.ask(
    "Check liquidation risk and identify if deleveraging is required"
  );
  console.log("Risk Check:", riskCheck);
}

testMonitoring().catch(console.error);

Agent Lifecycle

src/index.ts
async function main() {
  console.log("🤖 Initializing agents...");

  try {
    // 1. Get root agent
    const { runner } = await getRootAgent();

    // 2. Create sampling handler for cross-agent communication
    const samplingHandler = createSamplingHandler(runner.ask);

    // 3. Initialize specialized agents
    const { runner: telegramRunner } = await createTelegramAgent(samplingHandler);

    console.log("✅ Agents initialized successfully!");
    console.log("🚀 Agents are now running and ready...");

    // 4. Start monitoring service (see Automation guide)
    const monitoringService = new MonitoringService(
      "0 */1 * * *",
      "*/2 * * * *",
      telegramRunner
    );
    monitoringService.start();

    // Keep the process running
    await keepAlive();
  } catch (error) {
    console.error("❌ Failed to initialize agents:", error);
    process.exit(1);
  }
}

main().catch(console.error);

Next Steps

Tools & Functions

Learn how to create custom tools for your agents

Automation

Set up automated agent execution with cron jobs

ADK-TS Integration

Deep dive into ADK-TS integration patterns

API Reference

Explore the complete agent API documentation

Build docs developers (and LLMs) love