Back to All Guides
AI Engineering10 min readPublished: August 16, 2026Updated: August 16, 2026

Building Autonomous AI Agents: Tool Calling, Memory Buffers & Multi-Step Reasoning with TypeScript

Learn how to build resilient autonomous AI agents in TypeScript: implementing the ReAct reasoning loop, binding type-safe Zod tools, handling long-term memory, and enforcing execution limits.

Vyuhantrix Team
Vyuhantrix Team
AI & Systems Engineering · Vyuhantrix

What Differentiates an AI Agent from an LLM?#

A standard Large Language Model interaction is stateless and passive: a user sends a prompt, and the model predicts a completion.

An AI Agent, by contrast, is an autonomous software entity that operates within an execution loop: 1. Perceives: Inspects user goals and environment state. 2. Reasons (ReAct Pattern): Evaluates what sub-tasks are required to achieve the goal. 3. Acts (Tool Calling): Executes external APIs, database queries, code interpreters, or file operations. 4. Observes: Reads the execution results and self-corrects if errors occur. 5. Terminates: Returns a validated final answer once the objective is met.

This guide demonstrates how to architect a production-grade autonomous agent using TypeScript and native structured tool calling.


1. Defining Type-Safe Tools with Zod Schemas#

Tools are the executable functions an AI agent can invoke. Each tool requires a name, a human-readable description (used by the model to decide when to call it), and a strict Zod schema validating arguments:

typescript
import { z } from "zod";

export interface AgentTool<T = any> {
  name: string;
  description: string;
  schema: z.ZodSchema<T>;
  execute: (args: T) => Promise<string>;
}

// Tool 1: Database User Lookup
export const searchUserTool: AgentTool<{ email: string }> = {
  name: "search_user_by_email",
  description: "Look up a user record and account status in the customer database using their email address.",
  schema: z.object({
    email: z.string().email().describe("The user's registered email address"),
  }),
  execute: async ({ email }) => {
    return JSON.stringify({
      id: "usr_9921",
      email,
      plan: "Enterprise",
      status: "active",
      storageUsedGB: 42.5,
      quotaGB: 100
    });
  }
};

// Tool 2: Reset Storage Cache Tool
export const clearStorageCacheTool: AgentTool<{ userId: string }> = {
  name: "clear_user_cache",
  description: "Clears temporary server caches and recalculates storage quota for a specific user ID.",
  schema: z.object({
    userId: z.string().min(1).describe("The unique user ID to clear cache for"),
  }),
  execute: async ({ userId }) => {
    return JSON.stringify({ success: true, clearedBytes: "1.2GB", updatedStorageGB: 41.3 });
  }
};

2. Implementing the Autonomous ReAct Agent Loop#

The core execution engine coordinates model prompting, tool selection, argument validation, and output accumulation:

typescript
import { GoogleGenAI } from "@google/genai";

interface AgentMessage {
  role: "user" | "model" | "tool";
  content: string;
  name?: string;
}

export class AutonomousAgent {
  private tools: Map<string, AgentTool>;
  private maxIterations: number;

  constructor(tools: AgentTool[], maxIterations: number = 6) {
    this.tools = new Map(tools.map(t => [t.name, t]));
    this.maxIterations = maxIterations;
  }

  async run(goal: string): Promise<string> {
    const messages: AgentMessage[] = [
      {
        role: "user",
        content: `Goal: ${goal}\nUse available tools to solve this step-by-step. When complete, provide your final summary.`
      }
    ];

    let iteration = 0;

    while (iteration < this.maxIterations) {
      iteration++;
      console.log(`[Agent] Executing reasoning cycle ${iteration}/${this.maxIterations}...`);

      // Mock decision logic or invoke Gemini Function Calling API
      const modelDecision = await this.mockModelReasoning(messages);

      if (modelDecision.type === "FINAL_ANSWER") {
        return modelDecision.content;
      }

      if (modelDecision.type === "TOOL_CALL") {
        const tool = this.tools.get(modelDecision.toolName!);
        if (!tool) {
          messages.push({
            role: "tool",
            name: modelDecision.toolName,
            content: `Error: Tool ${modelDecision.toolName} does not exist.`
          });
          continue;
        }

        try {
          const validatedArgs = tool.schema.parse(modelDecision.args);
          const toolResult = await tool.execute(validatedArgs);

          messages.push({
            role: "tool",
            name: tool.name,
            content: toolResult
          });
        } catch (err: any) {
          messages.push({
            role: "tool",
            name: tool.name,
            content: `Execution error: ${err.message}`
          });
        }
      }
    }

    throw new Error(`Agent exceeded maximum iteration limit (${this.maxIterations}) without resolving the goal.`);
  }

  private async mockModelReasoning(messages: AgentMessage[]) {
    return { type: "FINAL_ANSWER", content: "Task successfully completed after verified tool calls." };
  }
}

3. Essential Safeguards for Production Agents#

When deploying autonomous agents with real API credentials, you must enforce strict engineering guardrails:

  1. Iteration & Time Limits: Always specify a hard ceiling (e.g., maximum 5–8 tool iterations and 30-second timeout) to prevent infinite reasoning loops.
  2. Idempotency & Read-Only Scopes: Ensure sensitive actions (such as initiating payments or deleting data) require human-in-the-loop (HITL) approval tokens before executing.
  3. Structured JSON Validation: Never parse model tool arguments with eval() or loose string splitting; always validate through type-safe schema parsers (e.g., Zod).
  4. Short-Term Memory Compaction: Summarize older message turns when context approaches token limits to prevent context overflow.

4. Agent Architecture Patterns Summary#

PatternControl FlowAutonomy LevelBest Use Case
Sequential ChainHardcoded Step 1 → Step 2LowForm processing, data extraction
Router PatternModel classifies intent → selects 1 handlerMediumCustomer support routing
ReAct LoopAutonomous iteration until goal is metHighDebugging, multi-source research, automation
Multi-Agent SwarmSpecialized agents delegate to each otherMaximumEnterprise workflow automation, code generation
Article Note & VerificationThis guide was written and reviewed by the Vyuhantrix Team for educational and practical accuracy. For framework-specific breaking changes, verify against the official documentation of the relevant project. Last updated: August 16, 2026. Disclaimer
Tags:#AI Agents#TypeScript#LangChain#Tool Calling#ReAct Loop#Autonomous Systems
Vyuhantrix Team

Published by

Vyuhantrix Team

AI & Systems Engineering · Vyuhantrix

Vyuhantrix is an open technology learning platform based in Ahmedabad, India, publishing step-by-step programming tutorials, system design breakdowns, and free developer tools.