Your agent does something it shouldn't, so you add a line to the system prompt. It still slips, just less often. Repeat that for a year and you have a long prompt the model half-follows.
The open-source harnesses (OpenHands SDK, OpenCode, Hermes Agent, DeepSeek harness, Strands) work differently. If a script can decide whether the model is doing the wrong thing, they check it in code when the model calls the tool. The call is rejected, and the error says what to do instead. The model reads that on its next turn, so it doesn't have to remember a rule from thousands of tokens ago.
Here is how that plays out on problems every agent hits.
It edits a file it never read
The usual fix is a prompt line: always read a file before editing it. But the harness already knows whether the file was read. DeepSeek keeps a record of every read and refuses the edit with edit requires reading "X" first (fs-observation-policy). The model reads the file and tries again.
It retries the same failing call
You could write don't repeat a command that failed. But "same tool, same arguments" is a string comparison. Hermes counts identical calls, and on the fifth it blocks with "Stop retrying it unchanged; change strategy or explain the blocker" (tool_guardrails.py). DeepSeek sends a reminder at 3, 5 and 8 repeats instead of blocking (repeat-tool-reminder).
It runs a command the wrong way
When the model wraps a command in nohup, Hermes refuses it and hands back the exact call to make: "Re-send WITHOUT the wrapper as terminal(command=…, background=true)" (terminal guards). OpenHands does the same when the model chains commands ("Cannot execute multiple commands at once", terminal_session.py) or passes a relative path ("Maybe you meant /abs/path?", editor.py). None of this needs a prompt paragraph; the mistake is visible in the call itself.
PDFs work the same way. If the model tries to cat a PDF, the harness can refuse and point to the parse tool. Better, the read tool can parse the PDF itself, save the text, and reply "Parsed. Read paper.md." The model never sees a failure.
It says "done" without testing
Always run the tests before finishing is another rule the run's own history can check. Hermes turns a final answer given right after a code edit into one more turn: "Run the relevant verification command now", at most three times (verification_stop.py). OpenHands lets a Stop hook refuse the finish and feeds its reason back as "[Stop hook feedback] …" (local_conversation.py).
Where the prompt still wins
Which source to search, or how to structure a report, is judgement, and a hard block there stops good runs too. These harnesses leave judgement to instructions that load when relevant: OpenHands loads skills by keyword and by the files the agent touches (trigger.py). Even plan mode is prompt-only in Hermes (plan_prompt.py) and DeepSeek (plan-mode README).
The line is simple: if a script can check it, enforce it at the tool call. If it needs judgement, put it in a skill.
Hooks let you add checks without touching tools
Every harness here also runs hooks, your own script before or after a tool call. DeepSeek turns a hook's deny into an error the model reads, and when several hooks answer, the strictest wins (merge.ts). OpenHands follows Claude Code's convention that a hook exiting with code 2 blocks the call (hooks/manager.py). OpenCode goes one step further: when a user rejects a call and types why, that text becomes the error the model sees (permission.ts).
Isn't this custom code?
No. It's the harness doing its job, and part of why OpenCode, Hermes and the OpenHands SDK each run past 20k lines outside their prompts. The full list of what a harness should have is in the companion post.
Next: find one line in your system prompt that starts with "never" or "always". If a script could check it, move it to the tool call.