DEV Community

Cover image for Agent knowledge is a trigger problem, not a writing problem
gyorgy
gyorgy

Posted on • Originally published at tsdevstack.dev

Agent knowledge is a trigger problem, not a writing problem

I put everything an agent needs to work in my framework into an MCP resource. Conventions, workflows, which files are generated, where secrets come from. It was accurate, it was complete, and it was one call away.

The agent almost never read it.

Meanwhile I was doing that job by hand. Stopping it mid-task. Correcting the same thing for the fourth time. Re-reviewing work I had stopped trusting three steps earlier. The knowledge existed, it was cheap to fetch, and it never arrived. I spent a while assuming I was prompting wrong.

I was not. A resource is passive. Passive means the agent has to decide to look, and it does not decide to look, because nothing tells it there is anything worth looking at. I had solved content and shipped zero delivery.

That is the part I had backwards. The four places you can put knowledge for an agent are not four kinds of content. They are four trigger conditions, and each one bills differently.

Four triggers, four prices

AGENTS.md fires every turn. Unconditional. It is also the only channel you pay for unconditionally, on every request, forever, whether or not this turn had anything to do with it.

MCP tools fire when the agent wants to act. The trigger is intent, which is reliable, because the agent already knows it needs to do something. You pay for the schemas sitting in context.

Skills fire when a description matches the situation. Cheap until they hit — the description is in context, the body is not. The match is the entire mechanism, and it is the one thing the other channels lack.

Docs fire when the agent decides to go read them. Which is rarely. Effectively free, and frequently worth exactly that.

Say it as a budget and the design falls out on its own. The always-on channel is the expensive one, so it holds the least: a router that says where to look, and the guardrails that must hold on every single turn. Never edit generated files. Read secrets through the service. That is it. Everything else has to earn its load by matching something.

Misrouting

Every failure I hit was the same failure: right content, wrong trigger.

A guardrail in a skill never fires, because "do not edit generated files" has no trigger. There is no moment that matches it. The agent edits the file, and the skill that would have stopped it wakes up never.

A walkthrough in AGENTS.md bills every turn for something that matters twice a month. You are paying rent on context you use almost never.

Workflow knowledge in a resource, or in docs, is the failure I already described. Nothing points at it, so nothing reaches it.

Two things I only learned by shipping it

Write against the running code. Building the auth skill, I found the docs naming one guard three different ways and describing the same header two. The code had one answer. A skill written from drifted docs teaches the drift, at the exact moment the agent is most likely to act on it.

Install it before you trust it. The first time I installed my own set, the tool rejected one skill over a formatting mistake in its description. It read fine. It did not parse. A skill that does not parse is not a weaker skill, it is no skill, and nothing tells you.

Also worth knowing before you lean on any of this: skills need an install step, and people skip install steps. The always-on file and the docs still have to carry anyone who never installs anything.

The point

Agent knowledge is not documentation. Documentation assumes a reader who goes looking. An agent does not go looking, and it starts from zero every session, so every session pays the onboarding cost again.

Which means the question is never "have I written this down." It is "what fires this, and what does firing cost." Get that wrong and you can have every answer sitting in the repo while the agent guesses in front of you.


This came out of adding a skill set to tsdevstack, an opinionated full-stack TypeScript framework that generates your infrastructure from one config file. The MCP server, the AGENTS.md, and the skills ship with it.

Top comments (5)

Collapse
 
mads_hansen_27b33ebfee4c9 profile image
Mads Hansen

This framing makes skill descriptions look less like documentation and more like a classifier surface. I’d test them that way: build a trigger corpus with clear positives, near-miss negatives, ambiguous overlaps, and prompts where two skills compete; then track precision, recall, false-unavailable cases, and unnecessary loads. Version the descriptions and regression-gate changes just like code. I’d also log which skills were considered, selected, or skipped and the matching evidence, otherwise misrouting stays anecdotal. One boundary still matters: unconditional safety rules cannot depend on semantic matching. Keep those in the always-on router or enforce them at runtime; use skills for conditional procedure, not for guardrails that must never miss.

Collapse
 
gyorgy profile image
gyorgy

Classifier surface is the right word, and it exposes something I left vague. I put guardrails in AGENTS.md because it is always on, but always on is not enforced. It is a reminder that is reliably present, and a reminder can still be ignored. Semantic matching is unreliable in an obvious way; unconditional instruction-following is unreliable in a quieter one.

What I actually run for the hard rules is hooks - per-file lint and typecheck on write, a Stop hook as a completion gate. Those fire on an event rather than a match, and they cost nothing in context. So the honest cost table has a fifth row, and it is the only one with a guarantee attached.

On the corpus: I do not have one. Logging is the part I can do first - which skills were considered, selected, skipped, and on what evidence - because without that there is nothing to build the corpus from.

Collapse
 
mansio profile image
Mikhail

The "right content, wrong trigger" framing is sharper than most agent-knowledge advice, and it maps directly onto a bug class I keep running into from the other side: implicit guardrails. I had a rule that should have applied ("don't resolve a symbol definition from experiments/ when the caller is in src/") that existed nowhere as an actual trigger — not in the tool logic, not in a skill description, nowhere. It just lived as an assumption, so of course it never fired, and a lookup silently resolved to the wrong file with no error.

Your AGENTS.md-vs-skills cost framing is a good lens for catching that class of bug before it ships: if a rule can only be described as "the agent should know not to do X," that's a signal it has no trigger yet, regardless of which of your four channels it's sitting in. Worth adding as a design-time check — for every guardrail, name the specific trigger condition, not just the rule text.

Mads's point about needing a trigger corpus with near-misses and competing-skill cases is the right next step too — that's effectively a test suite for routing, which most of us (myself included) don't have.

Collapse
 
gyorgy profile image
gyorgy

If a rule can only be described as the agent should know not to do X, it has no trigger yet" is a better statement of the check than anything in the post. I got as far as saying guardrails need a channel. You have named the test for whether one exists.

The experiments/ vs src/ case is the nastier shape too, because nothing errored. A misrouted skill produces visibly wrong work and you catch it. A missing trigger produces plausible work built on a silently wrong resolve, and you find that late or never.

Which suggests resolution rules do not belong in any of the four channels. That one belongs in the tool - the lookup should refuse the cross-boundary resolve rather than the agent being advised against it.

Collapse
 
mansio profile image
Mikhail

Yeah, that's the boundary I ended up at too.

Debugging the actual resolver made it obvious — the experiments/ → src/ rule already had everything it needed to enforce itself mechanically. Caller path, candidate path, category. Once I saw that, putting it in any advisory layer felt wrong.

The execution contract piece follows the same logic. "The agent should verify its changes" is just another instruction until something actually checks that the verification happened. That turned out to matter more than I expected.