Bridge — drive the agent from your phone
Approvals and safety
A dangerous action needs a human to say yes. Silence is not a yes — a timeout, a dropped connection and a refusal all deny.
When a connected agent wants to run something dangerous, it asks. The request reaches whichever client you are using, and the agent waits for an answer.
Only "yes" means yes
The policy is fail-closed, and it is worth stating exactly:
| What happened | Result |
|---|---|
| You approved | the tool runs |
| You refused | the tool does not run |
| Nobody answered in time | the tool does not run |
| The network failed while asking | the tool does not run |
The last two are the point. An agent that cannot reach a human must not become an agent that stops asking. If the approval request cannot be delivered, or the answer cannot be read, the action is denied — not deferred, not retried into silence, and never assumed.
The agent waits up to 10 minutes, checking every 2 seconds, and gives up after 10 consecutive network failures.
Every denial leaves a trace
A refusal writes an audit line naming the tool. All three kinds do — a human refusal, a timeout, and a failure to reach anyone — so a decision never vanishes from the transcript. An approval does not manufacture one.
The three are kept distinct in what the agent is told, which matters more than it sounds:
| What happened | What the agent reads |
|---|---|
| You refused | <tool> denied by human reviewer: <your reason> |
| Nobody answered in time | Approval timeout for <tool> — denied per fail-closed policy |
| The request could not be confirmed | Approval for <tool> could not be confirmed — denied per fail-closed policy |
A timeout is reported as a timeout, never as a person's decision. This was a real defect: an approval left unanswered for its full ten minutes denied correctly, and the model then wrote "the user declined" to somebody who had simply walked away from their phone. Fixed in v1.4.0.
Note what the third line does not contain. The underlying transport error is deliberately not quoted into it, because a transport error's text carries the request URL — an internal endpoint and a task id — and this line is rendered to people. The detail is not lost: it goes to the operator's log. The log and the audit line describe the same event and are written for different readers.
Everything the agent sends back to a client is scrubbed for secrets before it leaves the machine, at the point where an event becomes a wire message rather than at each sender — so a path added later inherits the guard instead of having to remember it.
Restricted tasks
A task can arrive with its own confinement attached, narrower than what the machine would otherwise allow:
- a tool allowlist — the agent may use only the named tools for that task;
- read-only — the task runs in Plan mode, with no workspace writes and no shell.
These are set when the task is dispatched from a constrained context, and the agent honours them for the duration of that task. They restrict; they never widen.
Delegated tasks from a head agent
A task can be issued by another agent rather than a person. Those carry a signed origin, and only a task whose signature verifies may auto-approve dangerous tools. A task that merely claims to come from a head agent, without a valid signature, falls back to the human approval flow — the claim is not the credential.
Turning approvals off
snaga --yolo connect
(--yolo is a top-level option, so it goes before the subcommand.)
This auto-approves every dangerous tool call without contacting anyone, and also disables the path-escape sandbox, so delegated tasks can write anywhere your user account can. It prints a warning on every start, deliberately, so it cannot be switched on once and forgotten.
Use it only where you would be comfortable handing someone your shell.