🤖 Your AI Agent is just a while loop with an API call

Let me prove it

Michał Michalczuk

Senior Fullstack Engineer @ Tektit consulting

tektitconsulting.com

michalczukm.xyz

import { ToolLoopAgent, stepCountIs, tool } from 'ai';
import { mistral } from "@ai-sdk/mistral";
import { z } from 'zod';

const weatherAgent = new ToolLoopAgent({
  model: mistral("mistral-large-3"),
  tools: {
    weather: tool({
      description: 'Get the weather in a location (in Fahrenheit)',
      inputSchema: z.object({
        location: z.string().describe('The location to get the weather for'),
      }),
      execute: async ({ location }) => ({
        location,
        temperature: 72 + Math.floor(Math.random() * 21) - 10,
      }),
    }),
    convertFahrenheitToCelsius: tool({
      description: 'Convert temperature from Fahrenheit to Celsius',
      inputSchema: z.object({
        temperature: z.number().describe('Temperature in Fahrenheit'),
      }),
      execute: async ({ temperature }) => {
        const celsius = Math.round((temperature - 32) * (5 / 9));
        return { celsius };
      },
    }),
  },
});

const result = await weatherAgent.generate({
  prompt: 'What is the weather in San Francisco in celsius?',
});
  • LLM provider bill for tokens
  • Tools/MCPs/Skills are not called
  • Provider's rate limiting

*Not to mention security, legal, data governance, comliance etc

💵 💶

Michał Michalczuk

michalczukm.xyz

Senior Software Engineer & Consultant
@ Tektit consulting

Talking head @various video formats

Let's create powerful agent from the scratch

*powerful != good or helpful
import readline from 'node:readline';

const SYSTEM_PROMPT = `You are a coding assistant.`;
const messages = [];

const chat = async () => {
  const res = await fetch('https://api.mistral.ai/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.MISTRAL_API_KEY}`,
    },
    body: JSON.stringify({
      model: 'mistral-large-2512',
      messages: [{ role: 'system', content: SYSTEM_PROMPT }, ...messages],
    }),
  });

  return (await await res.json()).choices[0].message;
};

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

for await (const line of rl) {
  messages.push({ role: 'user', content: line });
  
  const content = await chat();
  messages.push(content);

  process.stdout.write('🤖 ' + content.content + '\n> ');
}
node --env-file=.env src/agent.js
const SYSTEM_PROMPT = `You are a coding assistant with access to bash commands...`;

const messages = [];

const chat = async () => {
  const res = await fetch('https://api.mistral.ai/v1/chat/completions', {
	method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.MISTRAL_API_KEY}`,
    },
    body: JSON.stringify({
      model: 'mistral-large-2512',
      messages: [{ role: 'system', content: SYSTEM_PROMPT }, ...messages],
      tools: [
        {
          type: 'function',
          function: {
            name: 'sh',
            parameters: {
              type: 'object',
              properties: { command: { type: 'string' } },
            },
          },
        },
      ],
    }),
  });

  return (await await res.json()).choices[0].message;
};

const runTool = (input) => {
  try {
    return execSync(input + ';:') + '';
  } catch (error) {
    return error.message;
  }
};

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

for await (const line of rl) {
  messages.push({ role: 'user', content: line });

  while (true) {
    const content = await chat();
    messages.push(content);

    if (!content.tool_calls?.length) {
      process.stdout.write('🤖 ' + content.content + '\n> ');
      break;
    }

    for (const { id, function: { arguments: args } } of content.tool_calls) {
      const { command } = JSON.parse(args);
      messages.push({ role: 'tool', tool_call_id: id, content: runTool(command) });
    }
  }
}
const SYSTEM_PROMPT = `You are a coding assistant with access to bash commands...`;

const messages = [];

const chat = async () => {
  const res = await fetch('https://api.mistral.ai/v1/chat/completions', {
	method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.MISTRAL_API_KEY}`,
    },
    body: JSON.stringify({
      model: 'mistral-large-2512',
      messages: [{ role: 'system', content: SYSTEM_PROMPT }, ...messages],
      tools: [
        {
          type: 'function',
          function: {
            name: 'sh',
            parameters: {
              type: 'object',
              properties: { command: { type: 'string' } },
            },
          },
        },
      ],
    }),
  });

  return (await await res.json()).choices[0].message;
};

const runTool = (input) => {
  try {
    return execSync(input + ';:') + '';
  } catch (error) {
    return error.message;
  }
};

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

for await (const line of rl) {
  messages.push({ role: 'user', content: line });

  while (true) {
    const content = await chat();
    messages.push(content);

    if (!content.tool_calls?.length) {
      process.stdout.write('🤖 ' + content.content + '\n> ');
      break;
    }

    for (const { id, function: { arguments: args } } of content.tool_calls) {
      const { command } = JSON.parse(args);
      messages.push({ role: 'tool', tool_call_id: id, content: runTool(command) });
    }
  }
}
node --env-file=.env src/agent.js
docker sandbox run shell .
node --env-file=.env src/agent.js
[inside sandbox]
Add new tool in ./src/agent.js that will store memories in "memory.md" file in ./dist directory everytime user mentions that some information has to be memoized or stored or saved as memory.
[prompt]
const SYSTEM_PROMPT = `You are a coding assistant with access to bash commands...`;

const messages = [];

const chat = async () => {
  const res = await fetch('https://api.mistral.ai/v1/chat/completions', {
	method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.MISTRAL_API_KEY}`,
    },
    body: JSON.stringify({
      model: 'mistral-large-2512',
      messages: [{ role: 'system', content: SYSTEM_PROMPT }, ...messages],
      tools: [
        {
          type: 'function',
          function: {
            name: 'sh',
            parameters: {
              type: 'object',
              properties: { command: { type: 'string' } },
            },
          },
        },
        {
          type: 'function',
          function: {
            name: 'memorize',
            description: 'Store information in memory for later retrieval.',
            parameters: {
              type: 'object',
              properties: {
                content: {
                  type: 'string',
                  description: 'The information to be stored in memory.',
                },
              },
              required: ['content'],
            },
          },
        },
      ],
    }),
  });

  return (await await res.json()).choices[0].message;
};

const runShell = (input) => {
  // ';:' forces a zero exit status so execSync never throws on bad commands.
  try {
    return execSync(input + ';:') + '';
  } catch (error) {
    return error.message;
  }
};

const runMemorize = (content) => {
  try {
    const distDir = path.join(process.cwd(), 'dist');
    if (!fs.existsSync(distDir)) {
      fs.mkdirSync(distDir, { recursive: true });
    }
    const memoryFile = path.join(distDir, 'memory.md');
    fs.appendFileSync(memoryFile, content + '\n');
    return `Memory saved to ${memoryFile}`;
  } catch (error) {
    return `Failed to save memory: ${error.message}`;
  }
};

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

for await (const line of rl) {
  messages.push({ role: 'user', content: line });

  while (true) {
    const content = await chat();
    messages.push(content);

    if (!content.tool_calls?.length) {
      process.stdout.write('🤖 ' + content.content + '\n> ');
      break;
    }

    for (const { id, function: { name, arguments: args } } of content.tool_calls) {
      const parsedArgs = JSON.parse(args);
      let output;

      if (name === 'sh') {
        output = runShell(parsedArgs.command);
      } else if (name === 'memorize') {
        output = runMemorize(parsedArgs.content);
      } else {
        output = `Error: Unknown tool ${name}`;
      }

      messages.push({ role: 'tool', tool_call_id: id, content: output });
    }
  }
}
const SYSTEM_PROMPT = `You are a coding assistant with access to bash commands...`;

const messages = [];

const chat = async () => {
  const res = await fetch('https://api.mistral.ai/v1/chat/completions', {
	method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.MISTRAL_API_KEY}`,
    },
    body: JSON.stringify({
      model: 'mistral-large-2512',
      messages: [{ role: 'system', content: SYSTEM_PROMPT }, ...messages],
      tools: [
        {
          type: 'function',
          function: {
            name: 'sh',
            parameters: {
              type: 'object',
              properties: { command: { type: 'string' } },
            },
          },
        },
        {
          type: 'function',
          function: {
            name: 'memorize',
            description: 'Store information in memory for later retrieval.',
            parameters: {
              type: 'object',
              properties: {
                content: {
                  type: 'string',
                  description: 'The information to be stored in memory.',
                },
              },
              required: ['content'],
            },
          },
        },
      ],
    }),
  });

  return (await await res.json()).choices[0].message;
};

const runShell = (input) => {
  // ';:' forces a zero exit status so execSync never throws on bad commands.
  try {
    return execSync(input + ';:') + '';
  } catch (error) {
    return error.message;
  }
};

const runMemorize = (content) => {
  try {
    const distDir = path.join(process.cwd(), 'dist');
    if (!fs.existsSync(distDir)) {
      fs.mkdirSync(distDir, { recursive: true });
    }
    fs.appendFileSync(path.join(distDir, 'memory.md'), content + '\n');
    return `Memory saved to ${memoryFile}`;
  } catch (error) {
    return `Failed to save memory: ${error.message}`;
  }
};

for await (const line of rl) {
  messages.push({ role: 'user', content: line });

  while (true) {
    const content = await chat();
    messages.push(content);

    //.....

    for (const { id, function: { name, arguments: args } } of content.tool_calls) {
      const parsedArgs = JSON.parse(args);
      let output;

      if (name === 'sh') {
        output = runShell(parsedArgs.command);
      } else if (name === 'memorize') {
        output = runMemorize(parsedArgs.content);
      } else {
        output = `Error: Unknown tool ${name}`;
      }

      messages.push({ role: 'tool', tool_call_id: id, content: output });
    }
  }
}

What about multi-agent system?

Let's add it!

🤖

🤖

🤖

const MAIN_SYSTEM_PROMPT = `You are a helpful assistant with access to a coding specialist.
- You can help with general tasks and have access to bash commands.
- For ANY coding, programming, or software development task, you MUST delegate it to the coding agent using the "delegate_coding_task" tool.
- Do not try to write complex code yourself if it's better suited for the specialist.
- You can also save memories using "memorize".
- Be concise and practical.`;

const CODING_SYSTEM_PROMPT = `You are a specialized coding agent using the devstral-latest model.
- You are an expert in software development.
- You can execute bash commands using the "sh" tool to run tests, list files, or manage the project.
- You should focus purely on the coding task provided.
- When you are done, return a final response describing what you did.`;

// --- Tools ---

// --- Helper Functions ---

const runShell = (input) => {
  // ';:' forces a zero exit status so execSync never throws on bad commands.
  try {
    return execSync(input + ';:') + '';
  } catch (error) {
    return error.message;
  }
};

const runMemorize = (content) => {
  try {
    const distDir = path.join(process.cwd(), 'dist');
    if (!fs.existsSync(distDir)) {
      fs.mkdirSync(distDir, { recursive: true });
    }
    const memoryFile = path.join(distDir, 'memory.md');
    fs.appendFileSync(memoryFile, content + '\n');
    return `Memory saved to ${memoryFile}`;
  } catch (error) {
    return `Failed to save memory: ${error.message}`;
  }
};

const chat = async (model, messages, tools) => {
  const res = await fetch('https://api.mistral.ai/v1/chat/completions', {
    method: 'POST',
    dispatcher,
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.MISTRAL_API_KEY}`,
    },
    body: JSON.stringify({
      model,
      messages,
      tools: tools.length > 0 ? tools : undefined,
    }),
  });

  if (!res.ok) {
    const txt = await res.text();
    throw new Error(`API Error: ${res.status} ${res.statusText} - ${txt}`);
  }

  const data = await res.json();
  return data.choices[0].message;
};

// --- Agents ---

const runMainAgent = async (messages) => {
  const response = await chat('mistral-large-2512', messages, [
    {
      type: 'function',
      function: {
        name: 'sh',
        description: 'Execute a shell command',
        parameters: {
          type: 'object',
          properties: { command: { type: 'string' } },
          required: ['command'],
        },
      },
    },
    {
      type: 'function',
      function: {
        name: 'delegate_coding_task',
        description: 'Delegate a coding task to the specialist coding agent.',
        parameters: {
          type: 'object',
          properties: {
            task: {
              type: 'string',
              description: 'The detailed coding task description.',
            },
          },
          required: ['task'],
        },
      },
    },
    {
      type: 'function',
      function: {
        name: 'memorize',
        description: 'Store information in memory for later retrieval.',
        parameters: {
          type: 'object',
          properties: {
            content: {
              type: 'string',
              description: 'The information to be stored in memory.',
            },
          },
          required: ['content'],
        },
      },
    },
  ]);
  return response;
};

// The Coding Agent Loop
const runCodingAgent = async (task) => {
  console.log(`\n👷 [Coding Agent] Starting task: "${task}"`);

  const messages = [
    { role: 'system', content: CODING_SYSTEM_PROMPT },
    { role: 'user', content: task },
  ];

  // Limit turns to prevent infinite loops in demo
  const MAX_TURNS = 20;

  for (let i = 0; i < MAX_TURNS; i++) {
    console.log(`👷 [Coding Agent] Turn ${i + 1}`);
    const response = await chat('devstral-latest', messages, [
      {
        type: 'function',
        function: {
          name: 'sh',
          description: 'Execute a shell command',
          parameters: {
            type: 'object',
            properties: { command: { type: 'string' } },
            required: ['command'],
          },
        },
      },
    ]);
    messages.push(response);

    if (response.content) {
      console.log(`👷 [Coding Agent] says: ${response.content}`);
    }

    if (!response.tool_calls || response.tool_calls.length === 0) {
      // Agent is done
      console.log(`👷 [Coding Agent] Finished.`);
      return response.content;
    }

    // Handle tool calls
    for (const toolCall of response.tool_calls) {
      const { name, arguments: args } = toolCall.function;
      const parsedArgs = JSON.parse(args);
      let output;

      console.log(`👷 [Coding Agent] calling tool: ${name}`);

      if (name === 'sh') {
        output = runShell(parsedArgs.command);
      } else {
        output = `Error: Unknown tool ${name}`;
      }

      messages.push({
        role: 'tool',
        tool_call_id: toolCall.id,
        content: output,
      });
    }
  }

  return 'Coding agent reached maximum turns without completing.';
};

// --- Main Loop ---

const messages = [{ role: 'system', content: MAIN_SYSTEM_PROMPT }];

const rl = readline.createInterface({
  input: process.stdin,
  crlfDelay: Infinity,
});

console.log('🤖 Multi-Agent System Initialized');
process.stdout.write('> ');

for await (const line of rl) {
  messages.push({ role: 'user', content: line });

  while (true) {
    const response = await runMainAgent(messages);
    messages.push(response);

    if (!response.tool_calls || response.tool_calls.length === 0) {
      process.stdout.write('🤖 ' + response.content + '\n> ');
      break;
    }

    for (const toolCall of response.tool_calls) {
      const { name, arguments: args } = toolCall.function;
      const parsedArgs = JSON.parse(args);
      let output;

      if (name === 'sh') {
        console.log(`🛠️  [Main Agent] Executing shell: ${parsedArgs.command}`);
        output = runShell(parsedArgs.command);
      } else if (name === 'memorize') {
        console.log(`🧠 [Main Agent] Memorizing...`);
        output = runMemorize(parsedArgs.content);
      } else if (name === 'delegate_coding_task') {
        console.log(`👉 [Main Agent] Delegating to Coding Agent...`);
        output = await runCodingAgent(parsedArgs.task);
      } else {
        output = `Error: Unknown tool ${name}`;
      }

      messages.push({
        role: 'tool',
        tool_call_id: toolCall.id,
        content: output,
      });
    }
  }
}
const MAIN_SYSTEM_PROMPT = `You are a helpful assistant with access to a coding specialist.
- You can help with general tasks and have access to bash commands.
- For ANY coding, programming, or software development task, you MUST delegate it to the coding agent using the "delegate_coding_task" tool.
- Do not try to write complex code yourself if it's better suited for the specialist.
- You can also save memories using "memorize".
- Be concise and practical.`;

const CODING_SYSTEM_PROMPT = `You are a specialized coding agent using the devstral-latest model.
- You are an expert in software development.
- You can execute bash commands using the "sh" tool to run tests, list files, or manage the project.
- You should focus purely on the coding task provided.
- When you are done, return a final response describing what you did.`;

// --- Tools ---

// --- Helper Functions ---

const runShell = (input) => {
  // ';:' forces a zero exit status so execSync never throws on bad commands.
  try {
    return execSync(input + ';:') + '';
  } catch (error) {
    return error.message;
  }
};

const runMemorize = (content) => {
  try {
    const distDir = path.join(process.cwd(), 'dist');
    if (!fs.existsSync(distDir)) {
      fs.mkdirSync(distDir, { recursive: true });
    }
    const memoryFile = path.join(distDir, 'memory.md');
    fs.appendFileSync(memoryFile, content + '\n');
    return `Memory saved to ${memoryFile}`;
  } catch (error) {
    return `Failed to save memory: ${error.message}`;
  }
};

const chat = async (model, messages, tools) => {
  const res = await fetch('https://api.mistral.ai/v1/chat/completions', {
    method: 'POST',
    dispatcher,
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.MISTRAL_API_KEY}`,
    },
    body: JSON.stringify({
      model,
      messages,
      tools: tools.length > 0 ? tools : undefined,
    }),
  });

  if (!res.ok) {
    const txt = await res.text();
    throw new Error(`API Error: ${res.status} ${res.statusText} - ${txt}`);
  }

  const data = await res.json();
  return data.choices[0].message;
};

// --- Agents ---

const runMainAgent = async (messages) => {
  const response = await chat('mistral-large-2512', messages, [
    {
      type: 'function',
      function: {
        name: 'sh',
        description: 'Execute a shell command',
        parameters: {
          type: 'object',
          properties: { command: { type: 'string' } },
          required: ['command'],
        },
      },
    },
    {
      type: 'function',
      function: {
        name: 'delegate_coding_task',
        description: 'Delegate a coding task to the specialist coding agent.',
        parameters: {
          type: 'object',
          properties: {
            task: {
              type: 'string',
              description: 'The detailed coding task description.',
            },
          },
          required: ['task'],
        },
      },
    },
    {
      type: 'function',
      function: {
        name: 'memorize',
        description: 'Store information in memory for later retrieval.',
        parameters: {
          type: 'object',
          properties: {
            content: {
              type: 'string',
              description: 'The information to be stored in memory.',
            },
          },
          required: ['content'],
        },
      },
    },
  ]);
  return response;
};

// The Coding Agent Loop
const runCodingAgent = async (task) => {
  console.log(`\n👷 [Coding Agent] Starting task: "${task}"`);

  const messages = [
    { role: 'system', content: CODING_SYSTEM_PROMPT },
    { role: 'user', content: task },
  ];

  // Limit turns to prevent infinite loops in demo
  const MAX_TURNS = 20;

  for (let i = 0; i < MAX_TURNS; i++) {
    console.log(`👷 [Coding Agent] Turn ${i + 1}`);
    const response = await chat('devstral-latest', messages, [
      {
        type: 'function',
        function: {
          name: 'sh',
          description: 'Execute a shell command',
          parameters: {
            type: 'object',
            properties: { command: { type: 'string' } },
            required: ['command'],
          },
        },
      },
    ]);
    messages.push(response);

    if (response.content) {
      console.log(`👷 [Coding Agent] says: ${response.content}`);
    }

    if (!response.tool_calls || response.tool_calls.length === 0) {
      // Agent is done
      console.log(`👷 [Coding Agent] Finished.`);
      return response.content;
    }

    // Handle tool calls
    for (const toolCall of response.tool_calls) {
      const { name, arguments: args } = toolCall.function;
      const parsedArgs = JSON.parse(args);
      let output;

      console.log(`👷 [Coding Agent] calling tool: ${name}`);

      if (name === 'sh') {
        output = runShell(parsedArgs.command);
      } else {
        output = `Error: Unknown tool ${name}`;
      }

      messages.push({
        role: 'tool',
        tool_call_id: toolCall.id,
        content: output,
      });
    }
  }

  return 'Coding agent reached maximum turns without completing.';
};

// --- Main Loop ---

const messages = [{ role: 'system', content: MAIN_SYSTEM_PROMPT }];

const rl = readline.createInterface({
  input: process.stdin,
  crlfDelay: Infinity,
});

console.log('🤖 Multi-Agent System Initialized');
process.stdout.write('> ');

for await (const line of rl) {
  messages.push({ role: 'user', content: line });

  while (true) {
    const response = await runMainAgent(messages);
    messages.push(response);

    if (!response.tool_calls || response.tool_calls.length === 0) {
      process.stdout.write('🤖 ' + response.content + '\n> ');
      break;
    }

    for (const toolCall of response.tool_calls) {
      const { name, arguments: args } = toolCall.function;
      const parsedArgs = JSON.parse(args);
      let output;

      if (name === 'sh') {
        console.log(`🛠️  [Main Agent] Executing shell: ${parsedArgs.command}`);
        output = runShell(parsedArgs.command);
      } else if (name === 'memorize') {
        console.log(`🧠 [Main Agent] Memorizing...`);
        output = runMemorize(parsedArgs.content);
      } else if (name === 'delegate_coding_task') {
        console.log(`👉 [Main Agent] Delegating to Coding Agent...`);
        output = await runCodingAgent(parsedArgs.task);
      } else {
        output = `Error: Unknown tool ${name}`;
      }

      messages.push({
        role: 'tool',
        tool_call_id: toolCall.id,
        content: output,
      });
    }
  }
}
const MAIN_SYSTEM_PROMPT = `You are a helpful assistant with access to a coding specialist.
- You can help with general tasks and have access to bash commands.
- For ANY coding, programming, or software development task, you MUST delegate it to the coding agent using the "delegate_coding_task" tool.
- Do not try to write complex code yourself if it's better suited for the specialist.
- You can also save memories using "memorize".
- Be concise and practical.`;

const CODING_SYSTEM_PROMPT = `You are a specialized coding agent using the devstral-latest model.
- You are an expert in software development.
- You can execute bash commands using the "sh" tool to run tests, list files, or manage the project.
- You should focus purely on the coding task provided.
- When you are done, return a final response describing what you did.`;

// --- Tools ---

// --- Helper Functions ---

const runShell = (input) => {
  // ';:' forces a zero exit status so execSync never throws on bad commands.
  try {
    return execSync(input + ';:') + '';
  } catch (error) {
    return error.message;
  }
};

const runMemorize = (content) => {
  try {
    const distDir = path.join(process.cwd(), 'dist');
    if (!fs.existsSync(distDir)) {
      fs.mkdirSync(distDir, { recursive: true });
    }
    const memoryFile = path.join(distDir, 'memory.md');
    fs.appendFileSync(memoryFile, content + '\n');
    return `Memory saved to ${memoryFile}`;
  } catch (error) {
    return `Failed to save memory: ${error.message}`;
  }
};

const chat = async (model, messages, tools) => {
  const res = await fetch('https://api.mistral.ai/v1/chat/completions', {
    method: 'POST',
    dispatcher,
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${process.env.MISTRAL_API_KEY}`,
    },
    body: JSON.stringify({
      model,
      messages,
      tools: tools.length > 0 ? tools : undefined,
    }),
  });

  if (!res.ok) {
    const txt = await res.text();
    throw new Error(`API Error: ${res.status} ${res.statusText} - ${txt}`);
  }

  const data = await res.json();
  return data.choices[0].message;
};

// --- Agents ---

const runMainAgent = async (messages) => {
  const response = await chat('mistral-large-2512', messages, [
    {
      type: 'function',
      function: {
        name: 'sh',
        description: 'Execute a shell command',
        parameters: {
          type: 'object',
          properties: { command: { type: 'string' } },
          required: ['command'],
        },
      },
    },
    {
      type: 'function',
      function: {
        name: 'delegate_coding_task',
        description: 'Delegate a coding task to the specialist coding agent.',
        parameters: {
          type: 'object',
          properties: {
            task: {
              type: 'string',
              description: 'The detailed coding task description.',
            },
          },
          required: ['task'],
        },
      },
    },
    {
      type: 'function',
      function: {
        name: 'memorize',
        description: 'Store information in memory for later retrieval.',
        parameters: {
          type: 'object',
          properties: {
            content: {
              type: 'string',
              description: 'The information to be stored in memory.',
            },
          },
          required: ['content'],
        },
      },
    },
  ]);
  return response;
};

// The Coding Agent Loop
const runCodingAgent = async (task) => {
  console.log(`\n👷 [Coding Agent] Starting task: "${task}"`);

  const messages = [
    { role: 'system', content: CODING_SYSTEM_PROMPT },
    { role: 'user', content: task },
  ];

  // Limit turns to prevent infinite loops in demo
  const MAX_TURNS = 20;

  for (let i = 0; i < MAX_TURNS; i++) {
    console.log(`👷 [Coding Agent] Turn ${i + 1}`);
    const response = await chat('devstral-latest', messages, [
      {
        type: 'function',
        function: {
          name: 'sh',
          description: 'Execute a shell command',
          parameters: {
            type: 'object',
            properties: { command: { type: 'string' } },
            required: ['command'],
          },
        },
      },
    ]);
    messages.push(response);

    if (response.content) {
      console.log(`👷 [Coding Agent] says: ${response.content}`);
    }

    if (!response.tool_calls || response.tool_calls.length === 0) {
      // Agent is done
      console.log(`👷 [Coding Agent] Finished.`);
      return response.content;
    }

    // Handle tool calls
    for (const toolCall of response.tool_calls) {
      const { name, arguments: args } = toolCall.function;
      const parsedArgs = JSON.parse(args);
      let output;

      console.log(`👷 [Coding Agent] calling tool: ${name}`);

      if (name === 'sh') {
        output = runShell(parsedArgs.command);
      } else {
        output = `Error: Unknown tool ${name}`;
      }

      messages.push({
        role: 'tool',
        tool_call_id: toolCall.id,
        content: output,
      });
    }
  }

  return 'Coding agent reached maximum turns without completing.';
};

// --- Main Loop ---

const messages = [{ role: 'system', content: MAIN_SYSTEM_PROMPT }];

const rl = readline.createInterface({
  input: process.stdin,
  crlfDelay: Infinity,
});

console.log('🤖 Multi-Agent System Initialized');
process.stdout.write('> ');

for await (const line of rl) {
  messages.push({ role: 'user', content: line });

  while (true) {
    const response = await runMainAgent(messages);
    messages.push(response);

    if (!response.tool_calls || response.tool_calls.length === 0) {
      process.stdout.write('🤖 ' + response.content + '\n> ');
      break;
    }

    for (const toolCall of response.tool_calls) {
      const { name, arguments: args } = toolCall.function;
      const parsedArgs = JSON.parse(args);
      let output;

      if (name === 'sh') {
        console.log(`🛠️  [Main Agent] Executing shell: ${parsedArgs.command}`);
        output = runShell(parsedArgs.command);
      } else if (name === 'memorize') {
        console.log(`🧠 [Main Agent] Memorizing...`);
        output = runMemorize(parsedArgs.content);
      } else if (name === 'delegate_coding_task') {
        console.log(`👉 [Main Agent] Delegating to Coding Agent...`);
        output = await runCodingAgent(parsedArgs.task);
      } else {
        output = `Error: Unknown tool ${name}`;
      }

      messages.push({
        role: 'tool',
        tool_call_id: toolCall.id,
        content: output,
      });
    }
  }
}

What about other things?

- Tools

- MCP

- Skills

🤔

as the interface to inform LLM what is available in the agent

Think about tools

Where the tokens goes?

💵 💶

🤔

for await (const line of rl) {
  messages.push({ role: 'user', content: line });
  
  while (true) {
    // here goes HTTP call to Mistral API
    const content = await chat();
    messages.push(content);

    if (!content.tool_calls?.length) {
      process.stdout.write('🤖 ' + content.content + '\n> ');
      break;
    }

    for (const { id, function: { name, arguments: args } } of content.tool_calls) {
      const parsedArgs = JSON.parse(args);
      let output;

      if (name === 'sh') {
        output = runShell(parsedArgs.command);
      } else if (name === 'memorize') {
        output = runMemorize(parsedArgs.content);
      } else {
        output = `Error: Unknown tool ${name}`;
      }

      messages.push({
        role: 'tool',
        tool_call_id: id,
        content: output,
      });
    }
  }
}
// in chat(...)
const res = await fetch('https://api.mistral.ai/v1/chat/completions', {
  method: 'POST',
  dispatcher,
  headers: {...}
  body: JSON.stringify({
    model: 'mistral-large-2512', //'devstral-latest',
    messages: [{ role: 'system', content: SYSTEM_PROMPT }, ...messages],
    tools: [
      {
        type: 'function',
        function: {
          name: 'sh',
          parameters: {
            type: 'object',
            properties: { command: { type: 'string' } },
          },
        },
      },
      {
        type: 'function',
        function: {
          name: 'memorize',
          description: 'Store information in memory for later retrieval.',
          parameters: {
            type: 'object',
            properties: {
              content: {
                type: 'string',
                description: 'The information to be stored in memory.',
              },
            },
            required: ['content'],
          },
        },
      },
    ],
  }),
 });

What about

provider-level caching?

What About

context compression?

What About

<paste here>?

It is exceptionally hard to make it helpful and smart

It is easy to create powerful agent

  • Prompts
  • Security
  • Guardrails
  • Cost control
  • Agent(s) constelation
  • Workflow(s)
  • LLMs are stateless, each request contains full conversation

  • We are sending only definitions of skills, and definitions and schemas for MCPs tools and tools

    • LLM simply "tells" agent which should be used

  • Less agent loops is better

    • Each agent loop is extra input tokens (all previous steps including tools results) + new step

  • Agent can run on your local machine or on someone else's machine aka cloud

    • Tools are executed on that machine, not on LLM

    • Alternative - on microVMs

  • System prompts/Agent.md/Claude.md/Gemini.md etc are send basically in every request, thats why you should keep them lightweight

  • There is a lot to play with cache on provider side - if you have large system prompts - use it!

Takeaways

🗒️

Selected sources

FEEDBACK

❤️

Thank you!

Michał Michalczuk

michalczukm.xyz

 

Your AI Agent is a while loop with ifs

By Michał Michalczuk

Your AI Agent is a while loop with ifs

Debugging an AI agent feels like hitting a black box with a stick? Been there, done that. I've been building an AI agent that helps professionals prepare for meetings by processing emails, chats, and calendars with the Vercel AI SDK. I'll show you what's actually inside: loops, API calls, tool invocations, and a lot of glue. No magic - just code you can understand and debug. In this talk, I will reveal: - What actually happens during an agent's "thinking" – using real API call traces from a production system - How tool calling and MCP integration work under the hood (with live coding) - The orchestration and architecture patterns you have to take care of and be aware of You'll walk away knowing what your agent is doing when no one is watching. No more black boxes.

  • 87