Tools and the Agent LoopTools, and binding them to a model
No narration yet
Module 2, Lesson 120 min

Tools, and binding them to a model

The twice-daily todoist-hygiene job runs a prompted skill today. This module gives it a real agent brain: tools wrapping your existing scripts/todoist/client.py, emitting a plan that validates against the apply contract you already trust. Same safety, sharper filing.

A tool is a function the model can decide to call. You describe it, name, description, argument schema, and hand it to the model. The model, mid-generation, can emit a request to call it with arguments; your runtime executes it and feeds the result back.

Defining a tool
import { tool } from "langchain";
import * as z from "zod/v4";

const snapshotInbox = tool(
  async (input) => {
    // shell out to scripts/todoist/client.py snapshot, return JSON string
    return await runTodoist("snapshot", input.date);
  },
  {
    name: "snapshot_inbox",
    description: "Fetch a snapshot of the Todoist inbox for a given date.",
    schema: z.object({ date: z.string() }),
  },
);
Binding tools to a model
const withTools = model.bindTools([snapshotInbox]);
const res = await withTools.invoke(messages);
// res.tool_calls may contain requests you must execute, then loop back

That is the raw level: attach tools, the model gains the ability to request them, and the resulting tool_calls are requests you must execute yourself and feed back as tool messages.

Practice

Try it yourself

Recall

What a tool needs

These are the three the model itself depends on. The function body is not one of them.

What three things does tool(fn, {...}) require in its options?