Reported
The owner asked Heartfull (tmux) (cda75e28) to have an agent pull the latest code. It replied:
"…write access is currently blocked so I can't send commands directly. To enable this, please go
to the Settings tab and turn on write access for the terminal connector."
Write access was already granted. Live, on that instance:
terminal_run_command allowed:true reason:"ok" writeConsent:"granted"
terminal_send_keys allowed:true reason:"ok" writeConsent:"granted"
terminal_new_target allowed:true reason:"ok" writeConsent:"granted"
terminal_kill_target allowed:true reason:"ok" writeConsent:"granted"
It also never tried: the only execution recorded for that turn is terminal_list_targets. The agent
declined work it was permitted to do, invented a reason, and sent the owner to switch on a setting
that was already on.
Cause: the prompt states the gate and never states whether it is open
agent-think.ts:552 renders the tool list:
.map((t) => `- ${t.name}${t.scope === "write" ? " [write — needs the connector's consent]" : ""}: ${t.description}`)
That suffix is unconditional. Every write tool is labelled "needs the connector's consent"
whether or not the consent exists — and each tool's own description says it again
(connectors/terminal.ts:89,116,146: "WRITE: … requires terminal write consent").
So the model is told twice per tool that a gate exists and never once told the gate is satisfied.
Asked to run a command, the plainest reading of its own tool list is "I need a consent I do not
have" — so it refuses and helpfully explains how to grant it. The behaviour is not a
hallucination so much as the prompt's most natural interpretation.
The platform has the answer at that moment: writeConsent is resolved per tool and served to
/v1/instances/:id/tools (that is where the table above comes from). It is simply not put in front
of the model.
Why this one is expensive
- It converts a working agent into a broken one silently. Nothing errors; the owner is given a
confident, plausible instruction that cannot help, and the natural next step — toggling the
setting off and on again — changes nothing.
- It is worst on exactly the agents that matter: every runner-backed agent's useful tools are
writes.
- Consent exists to make a real refusal meaningful. A refusal that fires when consent IS granted
teaches the owner to distrust the gate.
Suggested fix
- Render the resolved state, not the rule:
[write — consent granted] / [write — consent NOT granted: ask the owner to enable the connector's write access in Settings]. Then a refusal is accurate and, when it is genuine, so is
the remedy.
- Say what to do when it is genuinely blocked, once, in the prompt — rather than leaving each
agent to compose its own version of the instruction. The current message names the right tab by
luck.
- Consider dropping the per-description repetition (
connectors/terminal.ts et al) once the
list carries the resolved state: two statements of a rule and none of the fact is what produced
this.
- Cheap guard: a test that a prompt built for an instance with granted consent does not
contain the string "needs the connector's consent" for a granted tool.
Same family as #395 and #398
The model asserted a platform state it had not checked, and the platform never offered it. #395 is
the same failure with tool results, #398 is why results are indistinguishable from claims. Here the
missing fact is a permission. In all three the platform knows and does not say.
Evidence: list_instance_tools(cda75e28) + instance_messages, 2026-08-08. Files:
workers/api/src/agent-think.ts:552, workers/api/src/lib/connectors/terminal.ts:89,116,146.
Reported
The owner asked Heartfull (tmux) (
cda75e28) to have an agent pull the latest code. It replied:Write access was already granted. Live, on that instance:
It also never tried: the only execution recorded for that turn is
terminal_list_targets. The agentdeclined work it was permitted to do, invented a reason, and sent the owner to switch on a setting
that was already on.
Cause: the prompt states the gate and never states whether it is open
agent-think.ts:552renders the tool list:That suffix is unconditional. Every write tool is labelled "needs the connector's consent"
whether or not the consent exists — and each tool's own description says it again
(
connectors/terminal.ts:89,116,146: "WRITE: … requires terminal write consent").So the model is told twice per tool that a gate exists and never once told the gate is satisfied.
Asked to run a command, the plainest reading of its own tool list is "I need a consent I do not
have" — so it refuses and helpfully explains how to grant it. The behaviour is not a
hallucination so much as the prompt's most natural interpretation.
The platform has the answer at that moment:
writeConsentis resolved per tool and served to/v1/instances/:id/tools(that is where the table above comes from). It is simply not put in frontof the model.
Why this one is expensive
confident, plausible instruction that cannot help, and the natural next step — toggling the
setting off and on again — changes nothing.
writes.
teaches the owner to distrust the gate.
Suggested fix
[write — consent granted]/[write — consent NOT granted: ask the owner to enable the connector's write access in Settings]. Then a refusal is accurate and, when it is genuine, so isthe remedy.
agent to compose its own version of the instruction. The current message names the right tab by
luck.
connectors/terminal.tset al) once thelist carries the resolved state: two statements of a rule and none of the fact is what produced
this.
contain the string "needs the connector's consent" for a granted tool.
Same family as #395 and #398
The model asserted a platform state it had not checked, and the platform never offered it. #395 is
the same failure with tool results, #398 is why results are indistinguishable from claims. Here the
missing fact is a permission. In all three the platform knows and does not say.
Evidence:
list_instance_tools(cda75e28)+instance_messages, 2026-08-08. Files:workers/api/src/agent-think.ts:552,workers/api/src/lib/connectors/terminal.ts:89,116,146.