Ask HN: How are you controlling AI agents that take real actions?

9 points by thesvp ↗ HN
We're building AI agents that take real actions — refunds, database writes, API calls.

Prompt instructions like "never do X" don't hold up. LLMs ignore them when context is long or users push hard.

Curious how others are handling this: - Hard-coded checks before every action? - Some middleware layer? - Just hoping for the best?

We built a control layer for this — different methods for structured data, unstructured outputs, and guardrails (https://limits.dev). Genuinely want to learn how others approach it.

8 comments

[ 3.2 ms ] story [ 30.0 ms ] thread
> Prompt instructions like "never do X" don't hold up. LLMs ignore them when context is long or users push hard.

Serious question. Assuming you knew this, why did you choose to use LLMz for this job?

Prompt guardrails are theater - they work until they don't. We ended up building sandboxed execution for each agent action. Agent proposes what it wants to do, but execution happens in an isolated microVM with explicit capability boundaries. Database writes require a separate approval step architecturally separate from the LLM context.

Worth looking at islo.dev if you want the sandboxing piece without building it yourself.

Hard-coded checks before every action, plus a governance layer that separates "what the agent wants to do" from "what it's allowed to do." The deeper issue: if your agent decides whether to issue a refund, you're solving the wrong problem with prompt guards. A refund is a deterministic business rule — order exists, within return window, amount matches. That decision shouldn't be made by an LLM at all.

In my setup, agents propose actions and write structured reports. A deterministic quality advisory then runs — no LLM involved — producing a verdict (approve, hold, redispatch) based on pre-registered rules and open items. The agent can hallucinate all it wants inside its context window, but the only way its work reaches production is through a receipt that links output to a specific git commit, with a quality gate in between.

For anything with real consequences (database writes, API calls, refunds), the pattern is: LLM proposes → deterministic validator checks → human approves. The LLM never has direct write access to anything that matters.

"Just hoping for the best" works until it doesn't. We tracked every agent decision in an append-only ledger — after a few hundred entries, you start seeing exactly where and how agents fail. That pattern data is more useful than any prompt guard.

Just treat the LLM as an NLP interface for data input. Still run the inputs against a deterministic heuristic for whether the action is permitted (or depending on the context, even for determining what action is appropriate).

LLMs ignore instructions. They do not have judgement, just the ability to predict the most likely next token (with some chance of selecting one other than the absolutely most likely). There’s no way around that. If you need actual judgement calls, you need actual humans.

I've been approaching this from a slightly different angle: treating the problem less as "agent alignment" and more as an execution boundary problem.

Instead of trying to force the model to behave via prompts or policies, we assume the model will eventually propose something unsafe. The trick is making sure it can't commit irreversible actions directly.

So the pattern we've been experimenting with is:

agent proposes an action

proposal goes through a deterministic gate

gate checks things like replay, state advancement, spend ceilings, etc.

only then does the real-world action execute

In practice this looks more like a transaction firewall than a prompt guardrail.

The LLM can reason however it wants, but anything that changes real state (payments, DB writes, API calls) has to pass through the gate.

It doesn't solve the reasoning problem, but it makes the commit boundary deterministic, which removes a lot of the scary failure modes like duplicate actions or retries gone wild.

Still early experiments, but the model behaving badly becomes much less dangerous if it literally can't execute without passing the boundary.