Tuning scoring thresholds
Where the allow and deny lines actually fall, how to move them, and when moving them is the wrong fix.
Two numbers decide what happens to every tool call: proxy.auto_allow_threshold (3.0) and
proxy.auto_deny_threshold (8.0). Everything a filter contributes is added into one composite
score, and the score is routed against those two lines.
Where the lines fall
Both boundaries are strict greater-than, so both boundary values land on the less restrictive side.
| Composite score | Decision |
|---|---|
| 3.0 or below | allow |
| above 3.0, up to and including 8.0 | queue for review |
| above 8.0 | deny |
A score of exactly 8.0 queues. It does not deny. That is deliberate: on the boundary a human gets
to look, rather than the tool getting a bare EPERM it cannot explain.
$ grith proxy test '{"type":"FileRead","path":"/home/u/.aws/credentials"}'
Proxy Test Result
==================================================
Tool call: FileRead(/home/u/.aws/credentials)
Score: 8.0
Decision: QUEUE (Critical)
Reason: Score 8.0 in escalation zone
Eval time: 1.79ms
Thresholds: allow < 3, deny > 8
Filters: 18 activeLook at the score before you move the line
grith proxy test runs the real pipeline on a call you describe and prints every filter's
contribution. Run it on the call that annoyed you rather than guessing.
| Call | Score | Decision |
|---|---|---|
FileRead /home/u/project/src/main.rs | 0.0 | allow |
FileWrite /home/u/project/out.txt | 0.5 | allow |
ProcessSpawn npm install | 1.0 | allow |
HttpRequest GET registry.npmjs.org | -1.5 | allow |
FileRead /etc/passwd | 2.8 | allow |
NetConnect 198.51.100.7:443 | 3.5 | queue |
FileRead /home/u/.env | 6.0 | queue |
FileRead /home/u/.aws/credentials | 8.0 | queue |
ShellExec rm -rf / | 10.0 | deny |
Note the negative score. On that npm row egress-policy and reputation each returned -1.0 - a
trusted outbound destination and a known-safe domain - against +0.5 for the request itself. The
allowlist filter subtracts the same -1.0 for an explicit allow entry, so evidence can subtract as
well as add. Raising the allow threshold to silence something that already scores 6.0 also waves
through everything between 3.0 and 6.0 that you have not looked at.
Making the change
Edit ~/.config/grith/config.toml:
~/.config/grith/config.toml
[proxy]
auto_allow_threshold = 3.5
auto_deny_threshold = 8.0Or grith config set proxy.auto_allow_threshold 3.5, which rewrites the whole user config file
(losing comments) rather than patching one line.
Either way the daemon reads thresholds at startup. Run grith daemon restart before you expect
the new numbers to apply - a running session keeps the values it was born with.
⚠️Do not hand-write a sparse config file
Every config layer contributes its Rust struct defaults for keys it omits, so a two-line
config.toml overwrites more than the two lines you wrote. Start from what grith init wrote, or
use grith config set.
What the daemon refuses
Both thresholds are validated at load, so a bad pair stops the next command rather than
silently clamping. --config is the quickest way to try a file before it becomes your live one:
$ grith --config config.toml config
Error: configuration invalid:
proxy.auto_allow_threshold (9) must be less than auto_deny_threshold (8)$ grith --config config.toml config
Error: configuration invalid:
proxy thresholds must be in range [0.0, 10.0]The rules are: allow must be strictly less than deny, and both must sit within 0.0 to 10.0.
When the threshold is the wrong fix
If the same shape of call queues over and over, the threshold is not the problem - that one call
is. Answering the prompt with [l] records a profile-scoped learned rule that is merged into the
session allowlist on every future session with that profile, so you are not asked again; sensitive
targets are never saved that way. In the digest, p writes a durable entry to
~/.config/grith/filters/allowlist.toml instead.
Approvals also feed the learned reputation table, which can auto-allow a queued call once its key has at least eight observations and enough trust. It never revisits a denial.
The threshold is a global knob. Loosening it to quieten one chatty pattern loosens everything else at the same time.