Skip to content
astorlm
← Map

Level 0

Your toolkit

Before any agent, four pieces. A model that only reads and writes text, a system prompt that tells it who to be, a list of messages that your code resends every time, and tools it can ask for. Everything later in this map is built from these.
1/16 Messages:
Before any agent, meet the pieces it is built from. This is the status screen, before the adventure starts.

EventBus

The four pieces

  • The model model

    The character

    Reads text, writes text. Knows a lot from training, but nothing about your app, your user or today.

  • The system prompt system

    Equip

    Instructions that sit at the top of every request: who it is, its rules, its tone, and facts it can’t know on its own.

  • The messages messages[]

    Bag

    The conversation so far. Your code keeps this list and sends all of it on every call.

  • The tools tools

    Skills

    Cards describing functions the model may ask for. It can only ask: your code does the running.

The model remembers nothing

This is the one that surprises people. A model has no memory between calls. Every request starts from zero, and the only things it knows are the ones inside that request: the system prompt, the messages, and the tool list.

In the animation, the second question arrives alone and the Oracle asks "which city?", even though it was told a moment ago. It only "remembers" once your code sends the earlier messages again. Chat apps feel like they remember because they resend the whole conversation every single time.

Two things follow from that. The history is yours to keep, trim and store. And every message you keep is sent again on every call, so a long conversation costs more each time.

Text, or a request

With tools on its list, a reply can be one of two things: text for the user, or a request to call a tool with some input. The model never runs anything. It writes get_forecast(city, date) and stops; running it is your code's job.

Notice the date: the model turned "tomorrow" into 2026-09-26 because the system prompt told it what today is. Facts it can't know on its own belong there.

The code

With astorlm: An astorlm agent holds the same four pieces. It keeps the history for you across run() calls, and when the model asks for a tool it runs it and sends the result back. That loop is level 2.

From scratch: The four pieces and a single request, no loop yet. Fill in the LLM block with your own endpoint, model and key.

import { OpenAIProvider, createLocalAgent, tool } from 'astorlm'
import { z } from 'zod'

// A tool: the card the model reads (name, description, schema) plus your code behind it.
const getForecast = tool({
  name: 'get_forecast',
  description: 'Daily forecast for one city: rain chance and min/max temp. date is YYYY-MM-DD.',
  schema: z.object({ city: z.string(), date: z.string() }),
  execute: async ({ city, date }) => forecastLine(city, date), // your code; the model never sees it
})

const agent = await createLocalAgent({
  // Any OpenAI-compatible endpoint: OpenAI, Ollama, LM Studio, vLLM, a proxy…
  provider: new OpenAIProvider({
    baseURL: 'http://localhost:11434/v1', // e.g. Ollama's default address
    model: 'your-model', // e.g. 'llama3.1', 'gpt-4o-mini'
    apiKey: 'YOUR_API_KEY', // local servers usually ignore it
  }),
  systemPrompt: 'You are Nimbus, a weather assistant. Today is 2026-09-25. Answer in one short line.',
  contextFiles: [], // by default astorlm also appends AGENTS.md and CLAUDE.md from the working folder
  tools: [getForecast],
})

// The agent keeps the history for you, so the second run knows about the first.
await agent.run('I’m in Buenos Aires.')
await agent.run('Will it rain tomorrow?') // asks for get_forecast(Buenos Aires, 2026-09-26), runs it, answers
console.log(agent.getMessages().length) // every message so far, resent on every call

What to watch

  • Keep the system prompt short and specific. It rides along on every call. Role, rules, tone, and the facts the model needs; not a manual.
  • Decide what the history keeps. Resending everything forever gets slow and expensive, and eventually doesn't fit. Trimming and summarizing it is its own pattern.
  • A model without tools will still answer. Ask it about live data and it will guess, fluently. If the answer depends on something it can't see, give it a tool.