Permissions
What your agent may do comes in two layers: what you grant it, and what its harness asks for beyond Link's defaults. By default your agent changes only its own folders and reaches the internet through a filtering proxy, in Link's sandbox.
Choose what your agent can reach
What you grant is your agent's own and follows it to any harness.
allow and deny restart the agent if it runs, and lnk agent show --permissions marks each grant as yours or its harness's (Allow what a
harness needs).
lnk agent show --permissions # what is on, what each opens, and whose
lnk agent allow --read '~' # your whole home, read only
lnk agent deny --internet-host '*' # no internet
lnk agent allow --internet-host api.anthropic.com # a host its proxy lets it reach
lnk agent allow --tcp github.com:22 # a port beyond HTTPS and HTTP
lnk agent allow --tool gh # a tool running outside the sandbox
lnk agent allow --per-minute 600 # at most 600 calls a minute on its proxy
lnk agent allow --port 5432 # a port of this machine, for a service
lnk agent start --sandbox sandbox.toml # all of it from a fileallow and deny
They take the flags lnk sandbox run takes, one for each key of a
sandbox's spec:
allow adds what they name ("*" takes the place of the rest of its
list, which holds it alone), and deny takes each item away again
(deny --network-mode host puts it back behind its proxy).
A deny never widens
So one that would is refused, the file as it was: --per-minute (a
limit changes only with allow --per-minute), one item of a list that
holds "*" (deny "*", then allow each), a folder taken from hide,
or one that leaves an OS's table ([internet.linux]) without a key it
gave, since that OS would then have the section's own (change that
table in the file itself).
By default
Its harness writes only its home, your files folder and /tmp/<name>*,
and reaches the internet only through Link's filtering proxy, never this
computer's other servers or your home network. What you grant opens
more.
Its sandbox file
What you grant is kept in the agent's sandbox file,
~/Link/Agents/<agent>/Config/sandbox.toml, a sandbox's spec, which
--sandbox-file reads and allow writes:
[files] # what it sees: the folders it may write, what only read
write = ["work"]
read = ["chats", "~"] # "~": your whole home, read only
[internet] # through its proxy
hosts = ["api.anthropic.com", "api.telegram.org"] # ["*"]: any public host
tcp = ["github.com:22"]
per_minute = 600
[localhost]
ports = [5432] # this machine's ports it reaches: a service's
[tools]
names = ["gh"]
[commands] # what its run tool may start; ["*"] for any
allow = ["sh", "python3", "git", "/opt/tools/bin/convert"]
[commands.macos]
developer_tools = true # Xcode's tools, read only, so git runs
[teams.research] # a team's shared folder: what of it it writes, what only reads
write = ["drafts"]Without a file
A section left out stays closed, as in any spec. Without a file, Link's
is used: its work written, the internet through its proxy, run's
usual programs, and on a Mac the developer tools.
A line refused
A line is refused, and the error names it, when it holds an unknown key,
a folder it doesn't see, unsandboxed (no sandbox is the agent's own
setting, lnk agent start --no-sandbox), another agent's memory,
scheduler, run or file (memory-<id>, scheduler-<id>, run-<id>,
file-<id>), a tool named as one of Link's namespaces (task, tool,
file, agent), a model's port (its model is its own), or a command
that isn't a program's name or an absolute path.
A file from an older Link
A sandbox file from an older Link, which named permissions, is read
once and written back as these sections: network as [internet] hosts = ["*"] (its hosts, tcp and calls with it), read-home as
[files] read = ["~"], open as [browser], developer-tools as
[commands.macos] developer_tools = true, and lan with network as
[network] mode = "host" (with localhost, every port).
What it can't say as narrowly
That is left out and said once: localhost without lan, which behind
its proxy reached every port (name each, --port), and lan without
network, which opened nothing. Its ports without network, which on
Linux it didn't reach, it reaches from then on, relayed into its sandbox
as on macOS, and that's said too.
Each grant
lnk agent show --permissions shows each thing it may do here, as its flag:
the developer tools only on a Mac. A table for another OS is still kept,
so an agent's grants work on both.
Hosts
[internet] hosts, --internet-host, on by default as ["*"]: with a
list, its proxy lets it reach only those. Keep its model's host and its
connections' on it, which are api.telegram.org, slack.com and
*.slack.com, discord.com and *.discord.gg, and *.signal.org.
"*" is any public host: deny --internet-host '*', then allow --internet-host for each, keeps it to a list.
Ports beyond HTTPS and HTTP
The proxy passes HTTPS and HTTP. Name anything else as host:port
(--tcp), such as github.com:22 for git over SSH with a key in the
harness's ~/.ssh. On Linux a database client reaches a named endpoint
too, but on a Mac only a client that takes a proxy command, like git
over SSH, does.
Tools
Add one with lnk sandbox tool add, then allow --tool. Any other
harness finds it in its own MCP settings, and Link Harness at
$LNK_TOOL_<NAME>. Each is an HTTP MCP server on its proxy, and calls
you didn't allow by name ask you first.
Calls and pages
With a limit (--per-minute), its proxy takes at most that many calls
a minute and answers the rest with a 429 until the minute has room.
[browser] hosts (--browser-host), off by default, opens a page in
your browser, asking you each time.
This machine's ports
[localhost] ports (--port), none by default, each named: a database
or a service running here. Its harness and its run reach them at the
same port, with or without the internet. Every port, "*", only with
[network] mode = "host". Moved to another machine, they're left out.
Your network and your home
[lan] hosts (--lan-host), off by default, reaches machines of your
network, through its proxy. [files] read = ["~"] (--read '~'), off
by default, reads your whole home folder, and on macOS
[commands.macos] developer_tools (--developer-tools), on by
default, reads Xcode's tools, so git runs.
Files
Its files folder, its Home, holds work/ (anything it makes) and
memory/ (the documents its memory searches); its own folder beside it
(~/Link/Agents/<agent>/Agent) holds instructions/ (what it's told to
be), skills/ and chats/, named as Home's folders are.
write and read
[files] write names the folders it may change, work by default, and
read those it may only read; it reads the rest of Home. Its
instructions and skills are yours: it writes only its notes, through its
memory's remember, and instructions under read locks those too.
All of Home
write = ["."] is the whole of Home, for a files folder that's a
repository it works in, beside which only instructions, skills and
chats are named. chats is written only by its
harness.
Each harness's
Link Harness's sandbox reads Home and its instructions and skills, and
writes only those and its conversations. A harness from outside Link
works in the whole of Home and never reaches its own folder, so for it
[files] holds only for Link's tools, and a start says so.
Commands
The programs Link Harness's run may start, each call in a sandbox of
its own made from this file. A name is found on the system's PATH
(/usr/local/bin, /usr/bin, /bin, and on a Mac
/opt/homebrew/bin), and only those this computer has are offered.
Link's are a shell, Python, Node, git, curl, jq and the usual file
tools.
Landlock
On Linux a finite list, or a sandbox file without [commands], needs
Landlock. Without that capability, the requested program is refused
before it starts. Choosing allow = ["*"] removes executable
restrictions while keeping the file and network restrictions enforced
by the sandbox. An allowed shell or Python interpreter can evaluate
code, whose processes inherit those file and network restrictions.
The network as it is
[network] mode = "host" (--network-mode host), off by default: for a
NAS, Home Assistant or a model on another computer that [lan] through
its proxy doesn't reach. It brings back the known gaps that lnk agent harness check shows as open.
What it opens nothing of
Nothing then filters or logs its network, so a list of hosts, tcp,
tools and pages, which only its proxy carries, open nothing, Link's own
tools among them (on its
proxy).
No sandbox at all
No sandbox is no grant: lnk agent start --no-sandbox runs your agent
without one, so its harness reads your whole home folder, until lnk agent start --sandbox. Every start warns, and lnk agent status shows
it. A harness that can't run in a sandbox says so, and its start is
refused until you add --no-sandbox.
Its proxy, then
It keeps its proxy, and its tools, the log and lnk sandbox stop with
it, but the proxy is then advice the harness may ignore, not a wall
(with no sandbox). The sandbox itself,
its proxy, its log (lnk sandbox log) and stopping every agent's way
out at once (lnk sandbox stop) are on the sandbox
page.
Allow what a harness needs
What a harness needs beyond your agent's grants is the harness's. It's asked when your agent switches to it, held only while it runs, and never given to another harness. A harness that needs nothing, such as Link Harness or DeepSeek Harness, runs with your agent's grants alone.
lnk agent use --harness openclaw # shows what it needs that your agent has not, and asks
lnk agent use --harness openclaw --yes # allows it without asking, for a script
lnk agent harness permissions --harness openclaw # what it needs and has now
lnk agent harness deny --network-mode host --harness openclaw # take it back
lnk agent harness allow --network-mode host --harness openclaw # give it back: only what it asks for
lnk agent harness reset --harness openclaw # ask again, at its next startWhat it says it needs
A harness says what it needs beyond Link's defaults, with why. That can
be a sandbox's spec, such as [network] mode = "host", shown as its
flags, or a risk of its own, by its own name, like OpenClaw's browser.
lnk agent harness allow and deny take the same flags as lnk agent allow, or a risk's name.
How lnk agent use asks
It shows every line the new harness needs that your agent hasn't, what it was given here before, and asks before anything changes. What it may do less of is said in a line and asks nothing. The first start on a harness, and any start after its needs grew, ask the same way before it runs.
! openclaw may do more on this machine than link.
GRANT IT OPENS WHY
--network-mode host this machine's network as it is, with no proxy openclaw says: Slack's websocket ignores Link's proxy (HTTPS_PROXY)
This holds for main, and every other agent here that runs openclaw.
No keeps it on link, and nothing changes.
Switch main to openclaw with these? [y/N]:No, and yes
No, or Enter, changes nothing, and your agent stays on the harness it
had, running; its next start asks again. Yes grants exactly those to the
harness, for every agent here that runs it, and starts it. What your
agent has of its own asks nothing, so a harness needing your home
(--read '~') runs without a question for an agent you granted it.
Without a terminal
--yes answers for you, and without it the switch or start fails and
says so. A harness that needs no sandbox at all is never asked: its
start is refused unless your agent runs with none (--no-sandbox),
which --yes never implies. A box, or a machine whose
~/.lnk/machine.toml says unsandboxed = false, refuses
--no-sandbox.
A risk it can run without
A risk the harness can run without, such as OpenClaw's browser, is
asked on its own, and no leaves it off while the harness runs. Without a
terminal, or with --yes, it stays off until you allow it.
Asked once
A later start asks only for what's new, never for what you allowed or
took back, and lnk agent harness allow, deny and reset change
or forget an answer. lnk agent move asks in your terminal before the
agent starts where it goes, and no leaves it where it was, running.
Said at every start
Every start of a harness running with more than the defaults says so,
and how to take it back, as in openclaw runs with --network-mode host, beyond Link's defaults (lnk agent harness deny --network-mode host --harness openclaw). lnk agent status shows the same in its
Sandbox row.
Check the sandbox
check tries, from inside the sandbox, what the harness shouldn't be
able to do, such as reading your home folder or other programs'
secrets, and reports each try.
lnk agent harness check --harness link
lnk agent harness check --harness hermesWhat it reports
blocked when the sandbox stopped it, allowed when a grant of yours
let it through, and open for a known gap, listed in
Security.
LEAK
Something no grant allows got through. The command fails, and please report it.
Run a command in its sandbox
run starts the command the way the harness runs, with its home as
HOME, in your agent's files folder, with its grants and through its
proxy. So lnk sandbox log shows its calls, as
<agent>-<harness>-run. It runs beside your agent, which keeps running.
# reach what your agent reaches, and nothing more
lnk agent harness run --harness link -- curl -sI https://example.com
# a shell, as your agent
lnk agent harness run --harness link -- sh
# the home of another harness
lnk agent harness run --harness hermes -- sh -c 'ls ~'When it goes wrong
What to do when a debugger fails, a start refuses no sandbox, or your agent can't reach a server, a NAS or its model is on Troubleshooting.