Your first agent
By the end of this page you’ll have an agent running in Docker on your machine, answering you in a terminal, and using a small tool of your own that reads a secret from its configuration. Every command below was run as written, and the outputs are copied from that run.
Before you start
Section titled “Before you start”You need three things installed:
- Bun, the JavaScript runtime Mercury runs on. Install it from bun.sh, then check it with
bun --version. - Docker, where the agent runs (on a Mac, Docker Desktop).
docker --versionshould answer, and Docker Desktop must be running. - Ollama, the program that serves the language model. Install it from ollama.com and pull two models: one that talks and can call tools, and one that turns text into numbers for the memory (an embedding model).
ollama pull <chat-model>ollama pull nomic-embed-text<chat-model> is yours to choose: any model in Ollama’s library that supports
tool calling works, and a bigger one answers better if your machine can take it. The agent runs inside Docker and
reaches Ollama on your machine at the address host.docker.internal, which is already the default; an Ollama on
another machine works too, through OLLAMA_HOST (step 2).
1. Create the app
Section titled “1. Create the app”An app is a folder with your agent in it: its configuration, its personality, and what Docker needs to run it.
bun create mercury-agent writes one for you.
bun create mercury-agent my-agent --yes--yes takes the defaults for everything. Without it, the command asks you the app’s name, the assistant’s name
and role, which channels and plugins to include, and a git remote; you can leave every answer at its default for
now. It ends like this:
Created my-agent in /…/my-agent bun install: done git: first commit on main
Next: cd /…/my-agent cp .env.example .env # then fill it in mfw start # bunx mfw start, without a global mfw
Optional, to have mfw everywhere: bun add -g @mercury-fw/cliThe app is also a git repository with a first commit, so you can see every change you make from here on.
2. Point it at your model
Section titled “2. Point it at your model”The settings that change from one machine to the next, and every secret, live in a file called .env, which is
never committed. The app comes with an example to copy:
cd my-agentcp .env.example .envOpen .env and fill in the chat model you pulled, the only line left empty:
OLLAMA_MODEL=<chat-model>The other lines already point at Ollama on your machine (OLLAMA_HOST; set it to http://<host>:11434 when
Ollama runs elsewhere), at the embedding model, and at the two places Mercury keeps its memory. The environment reference explains each one.
3. Start it
Section titled “3. Start it”mfw is Mercury’s command-line tool, and the app has its own copy: bunx mfw runs it.
bunx mfw startThe first start builds the Docker image, which takes a while. It starts two containers, the agent and Qdrant, the database behind the long-term memory:
Container my-agent-qdrant-1 Started Container my-agent-mercury-1 StartedThe agent is now a service waiting for messages from its channels. It has none yet, so the way to talk to it is the terminal.
4. Talk to it
Section titled “4. Talk to it”bunx mfw replA REPL is an interactive prompt: type a message, press Enter, read the answer. This is what the run above printed
for “Hi! Who are you?” (the model’s reasoning, printed in grey after Thinking…, is left out, and your model
words its answer its own way):
[~?k tokens] > Hi! Who are you?[turn] startThinking…I'm Mercury, an internal assistant for your team. I can search and read the shared wiki, keep personal notes for you, and help with questions about team conventions, project status, and workflows.[turn] done in 7.1s: 1 step, 0 tool calls, reasoning 232 chars, answer 196 chars, finish stop[~2k/~262k tokens] >The [turn] lines are for you, not for the person chatting: how long the answer took, and how many tools the model
called. It called none: the wiki it mentions is its own memory, which every app has, and no tool of yours is there
yet. The prompt shows how much of the model’s context the conversation fills. Press Ctrl+D to leave the REPL. The agent keeps running until
bunx mfw stop.
5. Give it a tool
Section titled “5. Give it a tool”An agent without tools can only talk. What it can do comes from plugins, and a plugin can be a package from npm
or a file in your app. Here you’ll write one: a tool that tells people the office guest Wi-Fi, whose password
lives in .env like every secret should.
Your first plugin walks through it line by line. In short, add the packages a plugin is written with:
bun add @mercury-fw/kit ai zodthen create src/plugins/guest-wifi.ts with the plugin from that page, declare it in mercury.config.ts, and add
its two settings to .env:
GUEST_WIFI_NAME=Office-GuestGUEST_WIFI_PASSWORD=correct-horse-batteryRestart, so the image picks up the new file and the container the new settings:
bunx mfw restart6. Check it uses the tool
Section titled “6. Check it uses the tool”bunx mfw repl[~?k tokens] > How do I get on the guest Wi-Fi?[turn] startThinking…Using guest_wifi…[tool] guest_wifi({})[tool result] {"ok":true,"network":"Office-Guest","password":"correct-horse-battery"}Thinking…Guest Wi-Fi:- Network: Office-Guest- Password: correct-horse-battery
Just connect to "Office-Guest" and enter the password and you should be online.[turn] done in 15.9s: 2 steps, 1 tool call, reasoning 147 chars, answer 151 chars, finish stopUsing guest_wifi… is the status line the person sees while the tool runs, and the [tool] lines show you the
model’s call and what came back: the answer is built on it.
The password never appeared in your code, only in .env.
Where to go next
Section titled “Where to go next”- Concepts explains the pieces you just used: the app, the core, channels, plugins.
- Plugins lists the ready-made ones, and how to add each.
- To let people reach the agent from somewhere other than your terminal, add a channel: Google Chat or HTTP.