Episode 11: a read-only agent that reads the security logs, one agent vs a crew of three
New: ops-readonly, the read-only twin of the episode 9 ops-actions runner (fixed question list, three read-only mounts, no docker socket, read_only, cap_drop ALL). Four role skills in agents/skills/, loaded at run time from this repo's Forgejo. Two workflows: E (one agent, seven tools, one skill) and F (three agents, one skill each, the workflow is the orchestrator). Measured over 20 runs: no run of either variant produced all numbers and lists correct. The solo agent confuses similar counts and skips a tool; the crew calls every tool but drops fields at each role boundary. Sharpening the skill files did not help the crew, it made it worse. Logs are attacker text: an instruction in a request path is carried into the report as data, not obeyed, but carried. Claude-Session: https://claude.ai/code/session_017iP581CYtPfxdZYPPAyWZA
This commit is contained in:
parent
bed41cfaf3
commit
d147f21490
13 changed files with 2088 additions and 0 deletions
|
|
@ -214,3 +214,46 @@ instead of 27,758.
|
|||
|
||||
Sub-workflows used as tools must be **active**, otherwise every call comes back
|
||||
as *"Workflow is not active and cannot be executed."*
|
||||
|
||||
## E and F - Security report, one agent vs a crew (episode 11)
|
||||
|
||||
The episode 9 agent read monitor state and triaged one incident. These two
|
||||
workflows read the security logs of the whole box once a day and write the
|
||||
report. They exist as a pair on purpose, to measure one question: does a 3B
|
||||
model do the whole job in one agent, or does splitting it into narrow roles
|
||||
make the report correct?
|
||||
|
||||
Both read through `ops-readonly`, the read-only twin of the episode 9
|
||||
`ops-actions` runner (see `ops-readonly/` and `HARDENING.md`). Neither agent
|
||||
gets a shell or a log file; both get a fixed list of questions.
|
||||
|
||||
| File | Shape |
|
||||
|---|---|
|
||||
| `e-security-report-solo.json` | One agent, seven tools, one skill file (`security-analyst-solo.md`). It reads everything and writes the report itself. |
|
||||
| `f-security-report-crew.json` | Three agents, one skill file each: `fail2ban-reader.md` reads SSH and fail2ban, `caddy-log-reader.md` reads the proxy log, `report-writer.md` turns both results into the report. The workflow itself is the orchestrator: the order is fixed, each agent gets exactly one skill as its system message. |
|
||||
|
||||
### Skills are files, loaded at run time
|
||||
|
||||
The four roles live in `agents/skills/*.md`. Each has frontmatter (name,
|
||||
description, tools), then the role, the allowed tools, an output schema and a
|
||||
short "what you do not do". The workflows fetch them at run time from this
|
||||
repo's own Forgejo over the docker network
|
||||
(`http://forgejo:3000/api/v1/repos/opsadmin/selfhostedops-stack/raw/agents/skills/<name>.md`,
|
||||
with the read-only Forgejo token), strip the frontmatter, and hand the body to
|
||||
the agent as its system message. Editing a role is editing a file and pushing
|
||||
it, not editing a workflow.
|
||||
|
||||
### Wiring
|
||||
|
||||
1. Create the `ops-readonly token` credential in n8n: Header Auth, name
|
||||
`x-ops-token`, value from `ops-readonly/token.env`.
|
||||
2. Import both JSON files, fill in the credential placeholders and
|
||||
`REPLACE_WITH_YOUR_OUTLINE_COLLECTION_ID`.
|
||||
3. Trigger with `POST /webhook/security-report-solo` or
|
||||
`/webhook/security-report-crew`. Body `{"deliver": false}` runs the report
|
||||
without writing to the wiki or pushing (used for the measurement runs);
|
||||
the default writes the report to the Ops Log and sends one ntfy line.
|
||||
|
||||
The measured comparison (correct numbers, invented numbers, runtime, tokens,
|
||||
and a prompt-injection test through a request path in the log) is in
|
||||
`lab-recordings-ep11/FACTS.md`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue