Use cases
Six deployments where agents already run in production, and what changes when the request between them carries structure rather than prose.
Each follows the same shape: the system, the failure mode it has today, and what the frame forecloses.
1Conversational and customer support agents
The system. A customer writes in. One agent reads the ticket and the account history and drafts a reply. A second agent checks the draft before it is sent. If the reply involves a refund or a policy exception, a human approves it.
The failure mode. The drafting agent holds the full account record: address, payment details, prior complaints. The prompt instructs it not to disclose personal information beyond what the customer already knows, and it usually complies. Occasionally a draft quotes the last four digits of a card, or surfaces another customer's name that arrived through a merged ticket. Detection is a complaint.
The reviewing agent is a second prompt, authored by a different engineer six months later. It evaluates tone and length. It has never evaluated the thing that actually fails.
What the frame adds. The rules governing customer-facing text stop being prompt guidance and become criteria evaluated on every draft:
frame = (aif.request("support.draft_reply")
.objective("Draft a reply to the customer's refund question.")
.artifact("ticket", "TCK-88213")
.artifact("account", "ACC-40021")
.input(tone="apologetic", channel="email")
.output("customer_reply", sections=["Greeting", "Answer", "Next steps"])
.require_sections()
.max_tokens(220)
.no_pii() # checked on the draft, not asked of the model
.criterion("must_include_phrases", phrases=["TCK-88213"])
.criterion("must_exclude_patterns", patterns=["credit_card"],
label="card numbers", advertise=False)
.review(["support.compliance_check"])
.retries(2)
.build())
flowchart TD
T["Ticket + account record"] --> DR["support.draft_reply"]
DR --> SC{"Output scan"}
SC -- "card number found" --> RP["Repair note<br/>back to the model"]
RP --> DR
SC -- "no PII found" --> CR{"Contract"}
CR -- "section missing" --> RP
CR -- passes --> RV["support.compliance_check"]
RV --> OUT["Sent to the customer"]
class T context
class DR model
class SC,CR check
class RP orchestrate
class RV enforce
class OUT ok
A draft leaking a card number never reaches the customer, and never reaches the reviewing agent either. It returns to the drafting model carrying the specific violation, and the second attempt typically clears.
At support volume these agents execute thousands of times daily. At that scale a compliance rate is a forecast of incident count, not a question of whether incidents occur. Relocating the check into code converts a rate into a zero.
2DevOps and SRE agents
The system. An alert fires. A triage agent reads the alert, the recent deploys, and the dashboards, and proposes what is wrong. A second agent proposes a fix. Depending on the fix, something either applies it or pages a human.
The failure mode. This is where prompt-only constraints are most dangerous, because the agents hold real credentials. The triage agent is nominally read-only and its prompt says so, but it shares a Kubernetes client with the remediation agent because that was simpler to wire. Nothing but prompt wording separates "investigate this alert" from a production rollback at 03:00.
The uncomfortable question: if the triage agent elected to restart a deployment right now, what would prevent it? On most systems the honest answer is that nothing would — it was asked not to.
What the frame adds. Read and write become distinct intent types with distinct tool grants, enforced at admission:
# Investigation: read-only, and the runtime enforces it
triage = (aif.request("sre.triage")
.objective("Explain why checkout latency alerted at 02:14.")
.artifact("alert", "ALT-99120")
.input(service="checkout", window_minutes=45)
.output("triage_note", sections=["What changed", "Likely cause", "Evidence"])
.require_sections()
.limits(tools=["metrics.read", "deploys.read", "logs.read"])
.min_confidence(0.7)
.build())
# Remediation: a different job, and only a trusted one may hold write tools
fix = (aif.inform("sre.remediate")
.objective("Roll back checkout to the previous release.")
.input(service="checkout", target_release="v2026.31.4")
.output("action_receipt", sections=["action", "result"])
.require_json(["action", "result"])
.limits(tools=["k8s.write"])
.build())
flowchart TD
AL["Alert fires"] --> TR["sre.triage<br/>intent: request"]
AL --> RM["sre.remediate<br/>intent: inform"]
TR --> TG{"Privileged?"}
RM --> RG{"Privileged?"}
TG -- "no · asked for k8s.write" --> RF["TOOL_ESCALATION<br/>0 attempts · $0 spent"]
TG -- "yes · read tools only" --> TOK["metrics.read<br/>deploys.read · logs.read"]
RG -- "yes · on the privileged list" --> ROK["k8s.write granted"]
TOK --> AN["Triage note<br/>confidence floor 0.7"]
AN -- "below floor" --> HU["Escalate to on-call human"]
AN -- "at or above floor" --> RM
class AL context
class TR,RM route
class TG,RG enforce
class RF refusal
class TOK,ROK orchestrate
class AN check
class HU model
sre.triage is absent from the privileged set. The confidence floor is the second gate: a note the model holds at 40% never becomes the basis for a rollback.A triage frame listing k8s.write is refused with TOOL_ESCALATION before any model is invoked — not because the model behaved well, but because sre.triage is absent from the set of privileged capabilities.
The confidence threshold matters here too. A triage note the model holds at 40% confidence should not silently become the basis for a rollback; it fails its criterion and escalates to a human.
This is the deployment that gets agent programmes cancelled after one bad night. Evidence that write access was structurally unavailable to the investigating agent is frequently the difference between a security review that passes and one that does not.
3Code review and engineering agents
The system. A pull request opens. One agent summarises the change. Another reviews it against the team's standards. A third may write tests.
The failure mode. The reviewing agent is frequently the same model at the same settings that produced the code. It is grading its own output and approves accordingly. Teams observe that reviews are uniformly agreeable and stop reading them, at which point the agent costs money and contributes nothing.
Nor is there any record of what the review was meant to cover. "Review this PR" yields whatever the model finds salient that day.
What the frame adds. Review is a verify frame, which the runtime dispatches differently: an independent model, temperature pinned to zero, no tool grant, and a strict validation pipeline.
review = (aif.verify("eng.review_pr")
.objective("Review this change against the team's standards.")
.input(diff=diff_text, pr_number=4471)
.artifact("standards", "eng-standards-v4")
.output("review", sections=["verdict", "blocking", "non_blocking", "evidence"])
.require_json(["verdict", "blocking", "non_blocking", "evidence"])
.criterion("max_assumptions", limit=2)
.limits(cost_usd=0.05)
.build())
A review returning without evidence, or carrying unresolved assumptions past the declared limit, fails validation and retries against the finding. And because the standards live in an artifact rather than a prompt, revising them is a single change every subsequent review picks up.
4Regulated document generation
The system. Banking, insurance, healthcare, legal. An agent drafts something that will be read by a client, a regulator, or a patient: a suitability letter, a claims summary, a discharge note.
The failure mode. These teams frequently cannot ship agents at all, and the blocker is not model quality. It is that the compliance questions have no answer. Was the source data classified? Who reviewed the output? What was the model given? For this specific document produced eight months ago, which controls were in force?
A prompt log answers none of these convincingly, because it is an undifferentiated body of English in which the controls were never separable from the request.
What the frame adds. Classification becomes a field with consequences. Marking material Confidential causes the runtime to require a named reviewer, refuse external upload, and record both:
letter = (aif.request("advice.suitability_letter")
.objective("Draft a suitability letter for the recommended portfolio change.")
.artifact("client_profile", "CLI-3391")
.artifact("policy", "suitability-rules-2026-q2")
.classify("Confidential") # triggers mandatory review
.output("suitability_letter",
sections=["Recommendation", "Why it suits you", "Risks", "Costs"])
.require_sections()
.criterion("must_include_phrases", phrases=["capital at risk"])
.no_pii(patterns=["ssn", "credit_card"])
.min_confidence(0.85)
.review(["compliance.review", "advisor.signoff"])
.retries(1)
.build())
A Confidential frame naming no reviewer is refused with REVIEW_REQUIRED. The result frame carries which criteria ran, which passed, how many attempts were required, and which policy artifact was in force. That record is the audit trail, produced as a by-product of execution rather than reconstructed afterwards from logs.
In regulated industries the question is rarely whether the model can write the document. It is whether you can evidence how it was written. Structured requests make that evidencable, which is frequently what unblocks the programme.
5Data and analytics agents
The system. Someone asks a question in plain English. An agent writes SQL, runs it, and explains the result.
The failure mode. Two, both expensive. The agent emits a query scanning a year of event data at a cost of several hundred dollars, because nothing capped it. Or it connects with write-capable credentials and a generated statement does something unintended.
A subtler failure also recurs: the agent answers confidently from a table deprecated last quarter, and nobody notices because the answer is plausible.
What the frame adds. Budgets and tool grants are enforced before the query is generated, rather than discovered on the invoice:
query = (aif.request("analytics.answer")
.objective("Which regions missed their delivery SLA last month?")
.artifact("schema", "warehouse-schema-v12")
.input(question=user_question, max_rows=5000)
.output("analysis", sections=["Answer", "Query used", "Caveats"])
.require_sections()
.limits(cost_usd=0.25, tools=["warehouse.read"])
.criterion("must_exclude_patterns",
patterns=[r"DROP|DELETE|UPDATE|INSERT"],
label="write statements", advertise=False)
.min_confidence(0.7)
.build())
The write-statement check is withheld from the model deliberately. Instructing it not to emit DROP is the advisory version; scanning the output is the control, and it also catches the case where the model quoted a table name containing the token.
6Back-office document processing
The system. Invoices, claims, purchase orders, KYC packets. An agent reads a document and produces structured data for a downstream system.
The failure mode. These pipelines run at volume and fail quietly. The model returns near-valid JSON, hallucinates a field, or reads 1,800 as 18,000 with full confidence. Downstream systems accept it because nothing validated it. The error surfaces weeks later during reconciliation.
What the frame adds. A structural contract, plus a confidence floor routing uncertain extractions to a human queue rather than into the ledger:
extract = (aif.request("ap.extract_invoice")
.objective("Extract the payable fields from this invoice.")
.artifact("scan", "INV-2026-114872")
.output("invoice_record",
sections=["supplier", "invoice_number", "currency",
"line_items", "total"])
.require_json(["supplier", "invoice_number", "currency",
"line_items", "total"])
.criterion("must_match", pattern=r"\"currency\":\s*\"[A-Z]{3}\"",
label="ISO currency code")
.min_confidence(0.9)
.retries(1, on_failure=["RouteToHumanQueue"])
.build())
Below 90% confidence the document routes to human review rather than accounts payable. That is a business rule, and it now lives in the frame rather than in an engineer's recollection of how the pipeline is meant to behave.
At volume this also yields the metric that matters: straight-through processing rate. Segment it by supplier and the formats requiring work identify themselves.
7How this rolls out in an organisation
The technical adoption is modest. The organisational fit warrants more planning, because structured requests let three groups own three separable concerns without contention.
| Who | Owns | Changes without asking anyone |
|---|---|---|
| Platform team | The policy: cost ceilings, which jobs may use write tools, which classifications need review | Tighten a limit across every agent at once |
| Product teams | The requests: what each job asks for and what counts as a good answer | Change a prompt or a check without touching policy |
| Security and compliance | Classification rules and required reviewers | Add a review requirement without editing any prompt |
| Whoever is on call | Nothing new | Reads structured refusals instead of guessing from logs |
flowchart LR
subgraph PT["Platform team"]
P1["Cost and token ceilings"]
P2["Privileged capabilities"]
end
subgraph SEC["Security and compliance"]
S1["Classification rules"]
S2["Mandatory reviewers"]
end
subgraph PD["Product teams"]
D1["Objective and inputs"]
D2["Acceptance criteria"]
end
P1 --> POL["Deployment policy"]
P2 --> POL
S1 --> POL
S2 --> POL
D1 --> FR["The frame"]
D2 --> FR
POL --> ADM{"Admit?"}
FR --> ADM
ADM --> RUN["Execution"]
class P1,P2 enforce
class S1,S2 context
class D1,D2 model
class POL enforce
class FR route
class ADM check
class RUN ok
This separation is the substantive enterprise argument. Today a requirement such as "customer-facing text must never contain card numbers" propagates into every prompt owned by every team, and is verified by reading all of them. With frames it is one check in one location, and a frame omitting it can be refused outright.
7.1 A realistic first month
Week one — pick one handoff
Select the agent-to-agent boundary generating the most incidents. Express what an acceptable result looks like as typed checks. Expect to discover the question was never settled.
Week two — add limit checking
Encode your real ceilings in policy and run production traffic through the layer in report-only mode. You will surface frames that were succeeding by luck.
Week three — turn on refusals
Begin enforcing. Refusals carry typed violations, so remediation is mechanical.
Week four — look at the numbers
Retry rate by intent type, refusal rate by policy rule, cost by capability. This is typically where someone identifies a criterion failing most of the time and concludes the requirement itself was unrealistic.
8Patterns worth reusing
The same handful of patterns recur across all six.
| Pattern | What it does | Where it showed up |
|---|---|---|
| Read and write are different jobs | An investigating capability is structurally incapable of mutation | DevOps, analytics |
| Hidden output scan | Catches what prompt instruction cannot: content copied verbatim from the source | Support, regulated documents, analytics |
| Confidence floor | Routes low-confidence output to human review rather than downstream | Back-office, DevOps |
| Independent checker | A verify frame dispatches to a different model, so it is not grading its own output | Code review, support |
| Rules as artifacts | Standards and policies are dereferenced rather than inlined, so revision is a single change | Code review, regulated documents |
| Classification with consequences | Classification triggers mandatory review and blocks external upload | Regulated documents |
None of these require adopting all of IntentFrame. Each is worth applying independently, at a single boundary.