Get Started

Link Harness is the harness your agent runs by default: Link's own, small and readable. It answers you, remembers the thread, and calls the tools you give it, such as your agent's memory. It runs no code: its tools run outside its sandbox. It installs in a second, with nothing from a third party. Every command is on the Agents page. How it compares with the other harnesses Link runs: Harnesses.

Needs: the agents plugins (lnk up agents). A hosted model's key (Anthropic, OpenAI or OpenRouter), which the provider bills, or a model on your computer (lnk up models), which is free.

Quickstart

lnk up agents                 # the harness and Link Harness plugins
ANTHROPIC_API_KEY=sk-ant-... lnk agent start
lnk agent connect telegram    # text it from your phone

Use a model

ANTHROPIC_API_KEY=sk-ant-... lnk agent start           # a hosted model, Link's default for it
ANTHROPIC_API_KEY=sk-ant-... lnk agent start --model claude-opus-5-5
lnk agent start --model qwen3                          # a model running on your computer

With no --model, it uses Link's default for the provider, as every harness does (Agents). It takes any runtime lnk model list finds, at its /v1 address. Behind its proxy it never holds a hosted key: Link's proxy adds it, outside the sandbox.

Switch to it, and back

lnk agent use link            # from another harness
lnk agent use hermes          # and back

Your model, files folder and channels come along. WhatsApp and Signal link again from a QR code the first time, since each harness keeps its own link. Each harness keeps its own memory: Link Harness starts with no conversations but its own.

Talk to it

Link Harness speaks every channel through Link: the channel's plugin carries your messages to it and its answers back, outside its sandbox.

lnk agent connect telegram
lnk agent connect slack       # a Slack app of yours, in Socket Mode: no public address
lnk agent connect discord
lnk agent connect whatsapp    # scan the QR code from the agent's phone
lnk agent connect signal      # the same, with a number of the agent's own

On Telegram, Slack and Discord the answer shows while it's written, edited in place. WhatsApp and Signal limit editing, so there it shows typing, then the whole answer. On Slack, 👀 on your message means it's being answered.

WhatsApp and Signal link as a device. What links them is kept in ~/.config/lnk/agents/<agent>/channels/<channel>, where the harness can't reach it. A move carries it, so they answer on the other machine as they are. After lnk agent disconnect and connect, they link again from a QR code.

It answers you only: your direct messages, and your mentions of it in a group, there, one at a time per chat. In a group it answers as a reply on Telegram and Discord, in a thread on your mention in Slack, and in the group on WhatsApp and Signal. Each group is a conversation of its own (Conversations/<channel>-<group id>), and your mention of it is taken out of the message it gets; a mention with nothing else is ignored. Each message is sent to it alone, and Link Harness adds the conversation before it.

Make it yours

Tell it who to be

# its instructions, read at every message
echo "Answer in French, in one sentence." > ~/Link/Agents/main/Home/Instructions.md

Without the file, it's told its spec's [instructions] base: Link's says to answer briefly, as a personal agent.

Change its opinions

How much of its model's window it uses, how hard it thinks, how many rounds of calls a message may take, what's kept of a tool's answer: each is a key of its spec, over Link's, and Link Harness holds none of its own (lnk agent spec prints them). It thinks where its model can: on Anthropic's newer models at the spec's effort (Link's: low), within its budget on one that takes a budget, and at the reasoning effort on OpenAI's reasoning models; a model Link doesn't know isn't asked to think. Its thinking is kept with the answer, and sent back with its calls, never shown.

Give it memory and tools

lnk agent memory use          # it searches your files and conversations
lnk sandbox tool add gh --allow list_issues -- github-mcp-server stdio
lnk agent allow tool gh       # it calls this one too

Ask "what did I say about driving to Albuquerque?" and it searches your memory, finds that conversation or a note you dropped in, and carries on from it. Each tool is an MCP server that Link runs outside the sandbox, and Link Harness calls it through its proxy. It sees memory's calls as memory__search, memory__read, memory__list and memory__links, and another tool's as <tool>__<call>. A call you didn't allow by name asks you first (lnk sandbox asks). Adding or removing a tool restarts your agent with it. A tool starts the first time a message calls it, and stops when the answer is sent. Memory keeps running for the messages after, until none has called it for 10 minutes, or for an hour at most (its spec's [tool.memory] keep and max_age).

Each call and its answer are kept in the conversation, like a message. It makes at most eight rounds of calls per message, then answers with what it has, and keeps 32 KB of each tool's answer (its spec's [turns] rounds and [tools] answer). A call may take five minutes, waiting for you to allow it included, then it's cancelled and the model told so ([tools] timeout, or [tool.<name>] timeout for one tool). Your model has to take tools: most hosted ones do, and in Ollama, models such as qwen3 do.

Its conversations

Read your conversations

ls ~/Link/Agents/main/Home/Conversations/
cat ~/Link/Agents/main/Home/Conversations/telegram-123456789/conversation.md
cat ~/Link/Agents/main/Home/Conversations/slack-D0123ABCDEF/conversation.md

Each chat is a folder in your files, named by its channel and chat. In it, each message is a file, 00000001.json and on, never changed once written, with its time, model, tokens as the provider counted them, and its cost: the provider's when it reports one, else those tokens at the model's price (lnk model facts). A tool's call is in the message that makes it, and its answer is a file of its own. conversation.md is a copy to read, added to as the agent answers (what it holds). window.json keeps where the model's window starts, so a message reads only the files from there; delete it and the next message reads them all and writes it again. turn.json is there while a message is answered: who answers it, renewed as its spec says ([turns] renew, Link's: every 10 seconds). They move with your agent (lnk agent move) and stay when you switch harness.

Messages from its schedules and subagents

Its scheduler (Link Scheduler) lets it start subagents and schedule messages to itself. Such a message comes as from them, never from you: it's kept with who sent it, and the model is told, in a line before it ("from your subagent ..., not your owner"), and each line of it is quoted (> ), so no paragraph of it reads as yours. Each tool call says which conversation it's in, and how many messages led to it, so a chain of agents waking each other stops at the spec's cap, and which tools the conversation has.

A subagent can be given fewer tools than its parent: its task comes with the list (Link-Tools), kept with its conversation (tools.json, beside its events), and from then on it's offered only those of its tools. A later list narrows it again, never widens it; a call to a tool it wasn't offered is answered as one there isn't.

Send another message while it answers

A message you send while it answers is kept at once, and then does what its spec says ([turns] busy):

  • steer (Link's): the answer takes it in at its next step, and goes on to answer it too, even past its last round of calls; the reply comes on your first message.
  • queue: it's answered after, on its own.
  • interrupt: the answer stops where it is, kept and marked interrupted, tools still running are cancelled, and your new message is answered.

If the harness stops mid-answer (a crash, the machine restarting), it finishes the answer when it starts again, or at the chat's next message: a tool call that hadn't answered isn't made again, the model is told so, and decides whether to call it again. One that had answered every message when it stopped is left as it was. An answer finished at its start comes to your chat too, from the agent's bridge, within a minute (its spec's [turns] lapse). A turn counts as stopped once its turn.json isn't renewed for that long (Link's: 60 seconds). The tools one step calls run at once.

What it costs and remembers

See what it costs

lnk measure main            # its turns, tokens, spend and times, over the last day

After each turn it reports, numbers only, its tokens, what it cost (as above), its tool calls and failures, and how long it took until the model was asked, until the answer's first piece went out, and until the answer was whole. They come from the turn's messages, never their words, and go to the file Link names (LNK_MEASURES), for the measure plugin (Measure).

How much it remembers

The model sees as much of the conversation as its window takes, as its spec says: Link's uses up to 128,000 tokens of it ([window] max), so a long conversation never runs up a surprise bill, and keeps a quarter of that for the answer ([window] answer, at most the model's longest; every provider is asked for no longer an answer) and an eighth back ([window] margin), since tokens are only counted roughly before a turn: four ASCII characters to a token, one for any other. The provider counts them exactly after, and those counts are what's kept, measured and priced.

What the model takes comes from what Link knows of it (lnk model facts): Link's figures, refreshed at every release, and yours, which win. A model on this machine gets the window its runtime says it runs with (Ollama, LM Studio, llama.cpp, vLLM), unless your models file says otherwise; any other model gets 32,768 tokens ([window] unknown). Link's max is held to the model's window; a max or [model] answer you set is used as you set it, whatever Link knows, so only the provider refusing a prompt as too long limits it, and the harness says so.

Past the window, the oldest turns drop, half the window at a time, so the prompt starts the same way for many messages and the provider's cache keeps it cheap. The files keep everything.

Troubleshooting

SymptomFix
It doesn't answer on a channellnk agent logs -f; the channel plugins' log is ~/.config/lnk/agents/<agent>/bridge.log.
"Your agent couldn't answer", and its log says "the model answered 401"Start it again with the right key: ANTHROPIC_API_KEY=... lnk agent start (or your provider's variable).
"no model named for ..."lnk agent start --model <name>.
"WhatsApp isn't linked" or "Signal isn't linked"lnk agent connect whatsapp (or signal) in a terminal, and scan the code.
It forgot something from long ago, or makes things up about itExpected past the window it's sent: Link's spec sends at most 128,000 tokens, 32,768 for a model Link doesn't know, or what Ollama runs it with. A larger window helps, at a higher price per message: [window] max in its spec (lnk agent spec), up to the model's own. The conversation's files keep everything; lnk agent memory use lets it search them.
"the model refused the prompt as longer than its window"The window you set is more than the model takes: set a smaller [window] max, or correct the model's window in ~/.config/lnk/model-facts.toml (lnk model facts <model>).
"the model answered 400 ... does not support tools"Pick a model that takes tools (lnk agent start --model qwen3), or lnk agent memory off.
A tool is missing from its answerslnk agent logs says why ("tool ... left out of this turn"); lnk agent permissions lists the tools it may call.

Guarantees and gaps: Agents Security. Why it works this way: Decisions, and why Link has a harness of its own: Agents Decisions. Working on its code: Developing.