Decisions
Why each run call gets a sandbox of its own, which programs it offers,
and how a command runs in the background.
Why does run run each call in a sandbox of its own, and file a session's in one?
So code runs only in a sandbox the agent's sandbox file makes. Link
Harness runs no code: it calls run and file as tools outside its
sandbox, through its proxy, and their calls run under lnk sandbox run
with flags made from the file. Nothing a run call starts outlives it:
a program left running or a file in /tmp is gone at the next call.
file runs only Link file, which starts nothing, so one sandbox with
the same flags serves a session's calls: a start costs tens of
milliseconds, a call in a running one about a millisecond.
Which programs does run offer?
Those of the sandbox file's [commands] this computer has, found at a
start on the system's PATH. The model is offered only those, by name,
in the tool's schema and in its environment section, so it never tries
Python where there is none, and a program it isn't offered is refused
twice, by the tool and by the sandbox itself.
No asking
There's no asking: [commands] allows or refuses. Link's list is a
shell, Python, Node, git, curl, jq and the usual file tools, so a script
works as it would in a terminal; ["*"] allows any program, and []
turns run off. run is granted in Link's default sandbox file on your
own machine, and a deployment's own default may leave it out.
Its PATH
The PATH it looks on is the system's: /usr/local/bin, /usr/bin,
/bin and the sbin folders, and on a Mac /opt/homebrew/bin first.
That is what a person's terminal finds without their own ~/bin.
Why does run take a program and its arguments, not a command line?
A program's name is what [commands] checks, and what the schema can
list. Arguments go as they are, with no shell reading them, so a quoted
path or a $ stays itself. A pipeline or a script is sh -c, where the
shell is one of the programs it may run.
What does run reach?
What the sandbox file grants the agent: the internet through a proxy of
the call's own when it has [internet], only its hosts unless "*",
its tcp endpoints, its per_minute, its tools, and your home folder
with read = ["~"]. It reads Home and the agent's instructions, skills
and conversations, and writes only the folders [files] write names, so
it can't rewrite a conversation. [localhost] and [browser] aren't
given to it: they're for the harness's own servers and your browser, not
a script's.
Why is a command stopped before its call times out?
A command stops a tenth before [tool.run] timeout, with everything it
started, so what it printed so far comes back and the harness isn't left
waiting on a call that can only time out. What it printed is kept to
[tool.run] output for each of its output and its errors, its start and
its end, which is where a program says what it's doing and how it ended.
Where is a team's folder for run and file?
file names it teams/<team>/ in its paths, beside the agent's own
folders, and keeps to what's granted of it. run reaches it by its
path, ~/Link/Teams/<team>/Shared, which its sandbox opens as granted.
Link Harness tells its model both.
Why are run and file only for Link Harness?
They're defined for a harness that keeps to the files folder's layout, which writes only its conversations there itself and leaves the rest to Link's tools. OpenClaw, Hermes Agent and DeepSeek Harness have files, a shell and code of their own, in the whole folder, so Link adds none. An agent whose sandbox is off has neither: code runs only in a sandbox.
Background commands
How a command runs in the background, when the agent is told it ended, and what happens to it when the agent stops.
How does a command run in the background?
Under a supervisor of its own, lnk-link-run supervise, which run
starts and which is up only while its command runs, so an agent with
none costs nothing. run's server ends with its turn, so it can't own a
command that outlives it. The command runs in the sandbox a
run__command call gets, in a process group of its own.
Its lock
The supervisor holds a lock on the command's record for its whole life,
which the system releases however it dies, so a free lock always means
it's gone. They're called background commands, not jobs: each is one of
the agent's run calls, on its computer, in its sandbox.
Calls of run
They are four calls of the run tool (start, list, read and stop), not
a tool of their own: a second tool would repeat the program, the
sandbox, [commands] and the grant, and could disagree with the first.
The defaults are opinions, so they're the spec's: 4 at once (a build, a
test run, a server and a download), an hour's timeout (a long test
suite), and output kept a day (a morning's builds read in the evening).
When is an agent told a background command ended?
When it ends, through the agent's bridge, as a message from run:<id>
to the conversation that started it, so it's never taken as yours. It
says how the command ended and its output's end, half of [tool.run] output as a command's end is kept.
At most once
It's told at most once. The record is marked before the message is
handed over, and unmarked only when the bridge can't be reached, as a
schedule is fired at most once. A message twice is worse than one lost
in a crash, and run__list still shows how it ended.
Down a chain
The message is one further down a chain than the call that started the
command, and a start as far down as [tool.scheduler] hops is refused,
so a command started each time one ends stops at the same cap as
messages.
What happens to a background command when the agent stops?
It ends. A command lives as long as its agent runs, so nothing is ever
left running with no agent to hear of it, and nothing started under
grants since changed runs on. A turn ending, run's server ending or
the bridge restarting leaves it running, and run__list finds it again.
What ends it
Stopping or restarting the agent, its service or the computer ends it, recorded lost and told when the agent's back.
The sweep
A sweep, as the bridge starts and at each turn, finds one whose supervisor died without a word. It kills what's left of its process group only when it's surely the command's: on the same boot, its leader the one recorded or gone, since a group's id isn't reused while any of it runs. A move or a delete stops every one, and none is carried, since a process can't move.
Why is a background command's output in the files folder?
So the agent reads it with its own tools, grep over a build's log
among them, not only a call at a time. It's background/<id>.out, which
the agent's sandboxes read and none writes unless [files] says so, and
an ending memory doesn't index, so a build's output doesn't crowd its
search. It's written outside the sandbox through descriptors, never
following a link. The record, which names the process group a sweep may
kill, is kept outside the files folder, in the agent's folder, where
nothing the agent runs can forge it.