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 file

allow 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 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 start

What 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 hermes

What 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.