DEV Community

ZNY
ZNY

Posted on

DEV.TO ARTICLE 31: Building AI Agents in Node.js: Complete Guide to Autonomous Task Execution

Target Keyword: "ai agent node.js tutorial"
Tags: ai-agents,nodejs,artificial-intelligence,programming,developer
Type: Tutorial


Content

Building AI Agents in Node.js: Complete Guide to Autonomous Task Execution

AI agents are one of the most transformative applications of large language models. An AI agent can reason, decide, and take actions — writing code, calling APIs, reading files — without constant human guidance. Here's how to build them in Node.js.

What Is an AI Agent?

An AI agent has three components:

  1. Planning — The LLM decides what actions to take
  2. Memory — Stores conversation history and context
  3. Tools — Functions the agent can call (web search, file I/O, API calls)

The agent loops: observe → plan → act → repeat until the task is complete.

The Core Agent Loop

class SimpleAgent {
  constructor(apiKey, tools = []) {
    this.client = new ClaudeAPI(apiKey);
    this.tools = tools;
    this.messages = [];
  }

  async think(task) {
    this.messages.push({ role: 'user', content: task });

    // Build system prompt with tool descriptions
    const systemPrompt = this.buildSystemPrompt();
    const fullMessages = [systemPrompt, ...this.messages];

    const response = await this.client.complete(fullMessages);
    this.messages.push({ role: 'assistant', content: response });

    return response;
  }

  buildSystemPrompt() {
    const toolDescriptions = this.tools.map(t =>
      `${t.name}: ${t.description}`
    ).join('\n');

    return {
      role: 'system',
      content: `You are an AI agent. You have access to these tools:
${toolDescriptions}

When you need to use a tool, respond with:
<Action>
{
  "tool": "tool_name",
  "input": { ... }
}
</Action>

When you complete the task, respond with:
<Done>your answer</Done>`
    };
  }
}
Enter fullscreen mode Exit fullscreen mode

Defining Tools

Tools are functions the agent can call. Here's how to define them:

const tools = [
  {
    name: 'web_search',
    description: "'Search the web for information',"
    execute: async (query) => {
      const response = await fetch(`https://api.example.com/search?q=${encodeURIComponent(query)}`);
      return response.json();
    }
  },
  {
    name: 'read_file',
    description: "'Read contents of a file',"
    execute: async (filepath) => {
      return fs.readFileSync(filepath, 'utf8');
    }
  },
  {
    name: 'write_file',
    description: "'Write content to a file',"
    execute: async ({ filepath, content }) => {
      fs.writeFileSync(filepath, content);
      return `Written ${content.length} characters to ${filepath}`;
    }
  },
  {
    name: 'run_command',
    description: "'Execute a shell command',"
    execute: async (command) => {
      const { stdout, stderr } = await exec(command);
      return stdout + stderr;
    }
  }
];
Enter fullscreen mode Exit fullscreen mode

Parsing Tool Calls

When the model outputs a tool call, parse and execute it:

async function executeToolCall(response) {
  const match = response.match(/<Action>\s*({[\s\S]*?})\s*<\/Action>/);
  if (!match) return null;

  const { tool, input } = JSON.parse(match[1]);
  const selectedTool = tools.find(t => t.name === tool);

  if (!selectedTool) {
    return { error: `Unknown tool: ${tool}` };
  }

  try {
    const result = await selectedTool.execute(input);
    return { tool, result };
  } catch (error) {
    return { tool, error: error.message };
  }
}
Enter fullscreen mode Exit fullscreen mode

Putting It Together: A Code Review Agent

Here's a practical example — an agent that reviews code:

class CodeReviewAgent extends SimpleAgent {
  constructor(apiKey) {
    const reviewTools = [
      {
        name: 'read_file',
        description: "'Read a source code file',"
        execute: async (filepath) => fs.readFileSync(filepath, 'utf8')
      },
      {
        name: 'list_files',
        description: "'List files in a directory',"
        execute: async (dir) => {
          return fs.readdirSync(dir).join('\n');
        }
      }
    ];
    super(apiKey, reviewTools);
  }

  async reviewProject(projectPath) {
    const files = await this.executeTool({ name: 'list_files', input: projectPath });
    const fileList = files.result.split('\n').filter(f => f.endsWith('.js'));

    const reviews = [];
    for (const file of fileList) {
      const content = await this.executeTool({
        name: 'read_file',
        input: `${projectPath}/${file}`
      });
      const review = await this.think(
        `Review this code for bugs, security issues, and best practices:\n\n${content}`
      );
      reviews.push({ file, review });
    }

    return reviews;
  }
}
Enter fullscreen mode Exit fullscreen mode

Adding Memory Persistence

For longer tasks, persist memory to disk:

class PersistentAgent extends SimpleAgent {
  constructor(apiKey, tools, memoryPath = './agent-memory.json') {
    super(apiKey, tools);
    this.memoryPath = memoryPath;
    this.loadMemory();
  }

  loadMemory() {
    if (fs.existsSync(this.memoryPath)) {
      this.messages = JSON.parse(fs.readFileSync(this.memoryPath, 'utf8'));
    }
  }

  saveMemory() {
    fs.writeFileSync(this.memoryPath, JSON.stringify(this.messages));
  }

  async think(task) {
    const response = await super.think(task);
    this.saveMemory();
    return response;
  }
}
Enter fullscreen mode Exit fullscreen mode

Safety Considerations

AI agents executing code can be dangerous. Always:

  1. Sandbox commands — Run in isolated containers
  2. Limit file access — Only allow specific directories
  3. Timeout long operations — Prevent infinite loops
  4. Review before execute — Log all actions for human review

Getting Started

The easiest way to power an AI agent is with ofox.ai — their OpenAI-compatible API gives you Claude's reasoning capabilities at competitive pricing. Set up an API key and start building agents in minutes.

👉 Get started with ofox.ai


This article contains affiliate links.


Tags: ai-agents,nodejs,artificial-intelligence,programming,developer
Canonical URL: https://dev.to/zny10289

Top comments (0)