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 phoneUse 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 computerWith 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 backYour 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 ownOn 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.mdWithout 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 tooAsk "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.mdEach 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 dayAfter 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
| Symptom | Fix |
|---|---|
| It doesn't answer on a channel | lnk 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 it | Expected 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 answers | lnk 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.
