# BROCS: Build, Run, Observe, Control, Secure > BROCS: Build, Run, Observe, Control, Secure. The surface where AI apps and agents meet the enterprise. BROCS is a vendor-neutral framework naming the five parts of the surface an organization must cover to adopt AI seriously: Build, Run, Observe, Control, and Secure. It is not a product. Canonical home: https://brocs.fyi/ ## B · Build: Enable people to make things. Tools, access, keys, and data for everyone who builds, technical or not. Roots: DevOps, DORA, platform engineering. Hands off to run. URL: https://brocs.fyi/build/ - Tooling: IDEs, agent CLIs, notebooks, chat surfaces - Access: who gets which tools, and how fast - Keys and models: distribution, scoping, rotation, BYOK - Data access: without handing out production credentials - Idea to production: golden paths, templates, scaffolds ## R · Run: Give the work somewhere to live. Apps, databases, secrets, provisioning, and the portability to move all of it. Roots: SRE, PaaS, hybrid cloud. Hands off to observe. URL: https://brocs.fyi/run/ - Runtime: where apps and agents actually execute - Data and state: provisioned, owned, backed up - Secrets: injected at runtime, never in code or chat - Provisioning: self-service, provision-build-deploy as one motion - Portability: the runtime goes where the data goes ## O · Observe: See what it is doing. Metrics, traces, and alerts, exposed to the people who own the thing. Roots: Observability, control theory. Hands off to control. URL: https://brocs.fyi/observe/ - Metrics: golden signals plus tokens, cost, tool calls - Traces: reconstruct what an agent did, with what, on what data - Alerts: routed to the builder who owns the app - What matters: signals that predict incidents, not dashboard decoration - Model behavior: drift, silent provider updates, quality regressions ## C · Control: Keep a hand on the wheel. Configuration, ingress, identity, storage, and routing you can change and roll back. Roots: Control theory, ClickOps to GitOps. Hands off to secure. URL: https://brocs.fyi/control/ - Configuration: declarative, versioned, reviewed, reversible - Ingress: one front door for internal AI apps - Identity: SSO by default, external access without VPN sprawl - Storage and backups: retention, lifecycle, restore drills - Routing: model and provider routing, pinning, failover ## S · Secure: Prove it is not going off the rails. Governance, agent oversight, cost accountability, and compliance evidence. Roots: SecOps, GRC, FinOps. Hands off to build. URL: https://brocs.fyi/secure/ - Governance: policy encoded where it is enforced, not a PDF - Agents: tool permissions, audit trails, human in the loop - Shadow AI: discovery of what people use when you give them nothing - Cost: who spends what, on which model, showback and chargeback - Compliance: HIPAA, SOC 2, PCI, FedRAMP, EU AI Act as platform output --- # Full text of every page ================================================================ # Build URL: https://brocs.fyi/build/ Summary: Enabling people, technical and not, to make things with AI: tools, access, model keys, and data, without a ticket queue in the way. **Build** is the part of the surface concerned with letting people in your organization make things with AI. It covers the tools they work in, the identity that gets them in, the model credentials they use, the data they can reach, and the path from an idea to something running. It is the letter almost everyone starts with, usually by buying a coding assistant, and the one most often mistaken for the whole surface. An assistant is one tile on Build. The rest of Build is what happens to the things people make with it. ## The claim If Build is missing, nothing else on the surface gets exercised, because nothing gets made. If Build is the *only* letter you cover, you have manufactured demand for the other four and no way to meet it: applications with no runtime, keys with no attribution, and a growing pile of useful things nobody can see, steer, or account for. The two tests that matter: 1. **How long from a new person's start date to their first shipped AI change?** Measured for an engineer, and measured for someone who is not one. 2. **If we replaced our primary AI tool next quarter, what would we have to rebuild?** If the answer includes identity, keys, data access, or runtime, those things are in the wrong place. ## The tension Build pulls against [Secure](/secure/) in the obvious way and against [Control](/control/) in a subtler one. Every guardrail is friction, and friction pushes people toward the unsanctioned path, which has no guardrails at all. The resolution is not to pick a side. It is to make the guarded path faster than the unguarded one, which is a platform problem rather than a policy problem. Read [idea to production](/build/idea-to-production/) first if you only read one page here. ================================================================ # Run URL: https://brocs.fyi/run/ Summary: The runtime underneath AI work: where apps and agents execute, the data and secrets they need, and the portability to run all of it where the data already is. **Run** is the part of the surface concerned with execution. Where AI applications and agents actually run, what they can reach from there, the databases and object stores and indexes they accumulate, the secrets they hold while working, how all of it gets provisioned, and whether any of it can move. It is the letter that vendors most often push back onto you. A product that covers a corner of [Build](/build/) and then says "deploy it on your infrastructure" has handed you Run, and Run is where the operational cost lives. ## The claim Long-running agents are not web requests. They are stateful, they hold credentials for the length of a session, they execute generated code, and they read untrusted content while doing it. A platform designed around stateless services has nowhere correct to put one, so it ends up on a machine somebody set up by hand. The second claim is about placement. In any organization large enough to be regulated, the data is not all in one place and will not be. The runtime therefore has to go where the data is, which means one system with multiple placements rather than a migration plan. ## The tests that matter 1. **Name the machine.** Where does a long-running agent execute today, and what can it reach from there: which network, which cloud role, which databases? 2. **Name the stores.** List everything your AI applications write to. If the list does not include the vector index and the prompt log, the list is incomplete. 3. **Name the second placement.** Could this run somewhere else, and what would break? ## The tension Run pulls against [Build](/build/): every isolation boundary is friction for the person trying to ship. It pulls against [Secure](/secure/) in the opposite direction, because the fastest runtime is the one with no boundaries at all. The [Replit incident](/resources/failure-modes/#replit-prod-db) is what the second tension looks like when nobody resolves it: an agent with production credentials, no separation to enforce, and a code freeze that was a request rather than a control. ================================================================ # Observe URL: https://brocs.fyi/observe/ Summary: Metrics, traces, and alerts for AI systems, exposed to the people who own them. Including the failures that return a 200 and look like nothing. **Observe** is the part of the surface concerned with seeing what your AI systems are actually doing: the numbers that say whether it works, the traces that say what it did, the alerts that reach the right person, and the measurements that catch quality moving underneath you. It is the letter organizations most often think they have covered because they have a monitoring stack. The monitoring stack is necessary and it will not catch the failure that matters most here. ## The claim Traditional monitoring detects systems that stop working. The characteristic AI failure is a system that keeps working and gets worse: the same latency, the same status code, a worse answer. Nothing on a conventional dashboard moves. That has two consequences. The first is that quality needs its own measurement, which means [evals](/observe/model-behavior/), canaries, and a way for users to flag a bad answer. The second is that [traces](/observe/traces/) are not a debugging luxury. They are the only record of what an agent did, and they are what an auditor will ask for. ## The tests that matter 1. **Cost, attributed.** Can you say what one application cost last month, without asking a vendor? 2. **Reconstruction.** For a specific agent run last week, can you list every tool call and every argument? 3. **Who finds out first.** If output quality dropped 20 percent tomorrow, would it be your measurement or your customer? ## The tension Observe pulls against [Secure](/secure/) more than people expect. The most useful trace is the most complete one, and the most complete one is full of prompts, tool arguments, and retrieved documents, which is to say full of exactly the data you are trying to protect. Redaction, retention, and access control on the telemetry itself are part of the job rather than an afterthought. Observe hands off to [Control](/control/): measurement without an actuator is a thermometer, not a loop. ================================================================ # Control URL: https://brocs.fyi/control/ Summary: Configuration, ingress, identity, storage, and routing: the ability to change what your AI systems do, and to change it back. **Control** is the part of the surface concerned with adjustment. Whether you can change what an AI system does, centrally, deliberately, and reversibly, and whether the change is recorded. It is the letter most often folded into [Run](/run/), and the distinction is worth holding: Run answers "is it up". Control answers "can I change it, and can I put it back". Plenty of organizations have an excellent Run story and no way to move a workload between model providers without editing application code. That is a real gap and it deserves a name. ## The claim Measurement without an actuator is a thermometer. [Observe](/observe/) tells you something is wrong; Control is what lets you do anything about it other than turning the system off. In practice the Control surface is five specific abilities: - Change a prompt, a model, or a policy, and roll it back. - Put every internal AI application behind one front door with SSO. - Carry a person's identity all the way to the data. - Say how long AI data lives, and prove it was deleted. - Move a workload between models or providers without touching code. ## The tests that matter 1. **Roll back a prompt.** Take a change from last month and time the revert. If it involves asking who made it, you do not have rollback. 2. **Change a provider.** Could one application move to a different model provider today, without a code change? 3. **Cut something off.** Can you stop one internal AI application reaching users in under five minutes without finding its owner? ## The tension Control pulls against [Build](/build/) constantly: every review gate and every central decision is a delay for the person shipping. The resolution is the same as everywhere else on the surface. Controls that are fast and inherited from a template get used. Controls that are queues get routed around, and the traffic that routes around them is invisible to you. Control hands off to [Secure](/secure/), which is where the same mechanisms have to produce evidence for somebody else. ================================================================ # Secure URL: https://brocs.fyi/secure/ Summary: Governance, agent oversight, shadow AI, cost accountability, and compliance evidence. What are the agents up to, and can you prove it? **Secure** is the part of the surface concerned with answering for the system: what it is permitted to do, what it actually did, what it cost, and whether you can show any of that to somebody who was not there. It is the letter most often treated as a phase rather than a property. Something gets built, it works, and then security and compliance are asked to bless it, which is the point at which everyone discovers that the necessary records were never produced. ## The claim Secure is not a subset of the other four letters and it is not a review gate at the end. It is a set of standing requirements that change what the other four have to emit. Three of them are genuinely different from pre-AI security work: **Untrusted content is an instruction channel.** Every document, ticket, and email an assistant reads can carry instructions to it. The perimeter model assumed data moves when a person moves it; an agent moves data continuously as a side effect of working. See [agents](/secure/agents/). **The blast radius is the union of standing access.** For a conventional service you reason about what a request can do. For an agent you have to reason about everything its tools and identity can reach, which is usually larger than anyone intended. **Spend is a security control.** An agent in a loop is a financial incident, and the control that stops it is a quota rather than a policy. See [cost](/secure/cost/). ## The tests that matter 1. **Blast radius.** For your most autonomous agent, list its tools, identity, data reach, egress, and cost ceiling. Can anyone produce that today? 2. **Shadow.** Pull six months of expense reports. What AI subscriptions are on personal cards? 3. **Evidence.** Could you answer an auditor's access and change questions for last quarter with a query rather than an investigation? ## The tension Secure pulls against every other letter, and the resolution is always the same: the controls that get used are the ones inherited from a fast path, and the controls that get routed around are the ones implemented as queues. A ban is the extreme case. It moves the activity somewhere you cannot see rather than stopping it, which is why [shadow AI](/secure/shadow-ai/) is a Secure problem with a [Build](/build/) solution. Secure hands back to Build: what you learn here changes what you are willing to let people make, and how quickly. ================================================================ # Manifesto URL: https://brocs.fyi/manifesto/ Summary: Why BROCS exists, why these five and no other set, and what the framework is arguing against. BROCS is how we came to think about the surface where AI apps and agents meet the enterprise. Five parts: Build, Run, Observe, Control, Secure. It started with a question a healthtech engineering leader asked after weeks of evaluating the AI tooling market: "I need somewhere to build it, somewhere to run it, a way to see what it's doing, and ensure it doesn't go off the rails." That sentence is Build, Run, Observe, Control. Add Secure for the conversation with the CISO, the compliance officer, and the regulated buyer, and you have the full surface. Most AI products occupy one part of that surface and push the other four onto "your infrastructure" or "your governance tooling". Customers integrate across three to five products, contracts, and audit processes, and the integration cost eats the productivity gain. A reasonable executive then concludes AI does not work for the enterprise, which is not the lesson the experience actually teaches. ## What BROCS is - A **vocabulary** for the whole surface, so buyers and builders can name what they are missing. - A **checklist** to run before adopting any AI tool: which letters does it cover, and what happens to the rest? - A **lifecycle**, drawing on DevOps, SRE, SecOps, platform engineering, and control theory, applied to AI adoption. ## What BROCS is not - Not a product. Not a vendor pitch. Any platform, commercial or homegrown, can be scored against it. - Not a maturity model. You do not finish Build and move on; the letters are continuous and the last one hands back to the first. - Not a compliance framework. It sits alongside the ones you already answer to and asks a different question: can your platform produce the evidence they want without a project. - Not "just give everyone Copilot". Assistants are one tile on the Build surface. The framework is about everything that happens after: where the things people build go, what they connect to, and how you keep them in check. ## What it is arguing against Three things, specifically. **That the tile is the product.** A coding assistant covers a corner of Build. Sold as an AI strategy, it manufactures demand for four letters nobody has staffed. **That the integration cost is somebody else's.** One tile per vendor times five tiles is three to five contracts, integrations, identity wirings, and audit processes. That cost is real, it lands on the customer, and it is where the productivity gain goes. **That partial coverage is a stage.** It is presented as an early phase of a journey. In practice organizations sit at partial coverage for years, and the [failure-mode library](/resources/failure-modes/) is what happens during those years. ## The five theses 1. **Tool churn is a given.** The enablement layer has to sit underneath the tools, or every switch is a re-platform. 2. **It goes where your data goes.** One system with multiple placements, not a migration plan. 3. **Sovereignty is a requirement, not a preference.** For some organizations it is a legal gate, and the sovereign paths have to be live options. 4. **Integration cost is the silent killer.** It is the mechanism by which a real productivity gain reads as net zero. 5. **Structurally it is an operating system.** Five parts that assume each other, a foundation apps, agents, and governance run on. ## Origin BROCS was coined by [Leo Mata](https://leomata.com/), who builds enterprise AI infrastructure at [Calliope AI](https://calliope.ai) and kept watching the same five gaps swallow adoption projects. The original write-up is at [leomata.com/blog/brocs](https://leomata.com/blog/brocs/), and that post remains the origin citation. This site is the canonical home for the framework. The framework text is published under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). Copy it, translate it, argue with it, put it on your own slides. Attribution to brocs.fyi is the only ask, and disagreement is more useful than agreement: if a letter is wrong, the framework should change. ================================================================ # Resources URL: https://brocs.fyi/resources/ Summary: The assessment, the failure-mode library, the glossary, and the reasoning behind the five. Four things, all free, all vendor-neutral, none of them a lead-capture form. - **[The assessment](/resources/assessment/)**. Twenty statements, four per letter. Score the ones that are true today and you get a scoreline like `B3 R2 O1 C2 S0`. It takes three minutes and it is designed to produce an uncomfortable number, because the useful output is a nameable gap rather than a good result. - **[The failure-mode library](/resources/failure-modes/)**. Public incidents, each mapped to the letter that was skipped, each with a source you can check. Filterable by letter. - **[The glossary](/resources/glossary/)**. The vocabulary, defined tersely and linkably. - **[Why five](/resources/why-five/)**. Why these five and no other set, and what was considered and rejected. - **[Adjacent practices](/resources/adjacent-practices/)**. How BROCS sits with DevOps, SRE, SecOps, platform engineering, and the compliance frameworks you already answer to. ## The origin essay BROCS was first written up at [leomata.com/blog/brocs](https://leomata.com/blog/brocs/). That post is the origin citation; this site is the canonical home for the framework itself. ## Reuse Take it. The framework text is meant to be copied, quoted, translated, argued with, and put on your own slides. Attribution to brocs.fyi is the only ask. There is a machine version at [/llms.txt](/llms.txt) and a full-text dump at [/llms-full.txt](/llms-full.txt) if you are feeding it to something. ================================================================ # Configuration URL: https://brocs.fyi/control/configuration/ Summary: Declarative, versioned, reviewed, rollback-able configuration for apps, prompts, models, and routing. Configuration is everything that changes system behaviour without changing application code: prompts, model selection, routing rules, tool definitions, retrieval settings, guardrail policies, and feature flags. In most AI stacks this material lives in three places at once: a database table edited through an admin panel, environment variables set at deploy time, and a few strings in the code. Nobody can say what the current state is, and nobody can put it back. ## The prompt is configuration and it is load-bearing A prompt is the most behaviour-changing artifact in the system and the one most likely to be edited in a text box by whoever is closest to the problem at four in the afternoon. Treat it like code, because it is: - **In version control**, with a diff and an author. - **Reviewed** by someone other than the person who changed it, at least for anything customer-facing. - **Tested** against the [eval suite](/observe/model-behavior/) before it ships. - **Deployed** through the same pipeline as everything else, with the same ability to roll back. - **Attributable at runtime**: given a response, you can say which prompt version produced it. The last one is the difference between "we think we changed it last Tuesday" and knowing. The common objection is that prompts need to be editable by non-engineers, quickly. That is reasonable and it does not require abandoning review. A prompt-editing surface that commits to a repository and opens a pull request satisfies both. What does not satisfy either is a production text box with no history. ## Declarative, not imperative The state of the system should be described somewhere, and something should make reality match the description. The alternative, a sequence of changes applied by hand through a console, has the property that the current state exists only in the system itself and cannot be reproduced. For AI configuration this matters more than usual because the surface is large and changes frequently. Which model each application uses, which tools each agent can call, which documents each assistant may retrieve, and what the guardrails allow are all security-relevant and all easy to change quietly. ## Rollback is the actual requirement Everything above exists to serve one property: when a change makes things worse, you can put it back quickly and know that you did. Test it. Pick a prompt change from last month and time how long it takes to revert it in production. If the answer involves finding who made it and asking what it used to say, you do not have rollback, you have an archaeology practice. Two specific traps: **Reverting the prompt does not revert the index.** If a change also rebuilt a retrieval index, putting the prompt back leaves you in a state that never existed before. **Reverting configuration does not revert a model version.** If the provider moved the model underneath a floating alias, your rollback restores your side of the change only. See [routing](/control/routing/). {{< aside title="How GitOps thinks about this" >}} The GitOps position is that the repository is the source of truth and the running system converges on it, so drift is detectable by definition. AI stacks tend to violate this early, because admin panels are the natural way to ship a prompt editor, and an admin panel writes directly to the running system. Making the panel a client of the repository rather than a writer to the database is the whole fix, and it is much easier before there are three panels. {{< /aside >}} ## Environments have to differ, on purpose Development, staging, and production will use different models, different keys, different data, and often different guardrail settings. That is correct. What is not correct is for those differences to be undocumented, which is how a staging prompt reaches production or a production key ends up in a notebook. Keep the shape of the configuration identical across environments and let only values differ, so a diff between environments is short and readable. {{< checklist >}} - Where is the current production prompt, and who changed it last? - Given a response from yesterday, can you identify the prompt version that produced it? - How long would it take to roll back a prompt change, and has anyone tried? - Is model selection configuration, or is it in application code? - Which tools can each agent call, and where is that list? - Can you diff staging configuration against production in one command? {{< /checklist >}} ================================================================ # Governance URL: https://brocs.fyi/secure/governance/ Summary: Policy encoded where it is enforced, not written where it is filed. Governance is the set of rules about what your organization will and will not do with AI, and the mechanisms that make those rules true. The second half is the part that usually does not exist. ## The document is not the control Most organizations write an AI policy early. It says sensible things: do not put customer data in unapproved tools, use approved models, get review before customer-facing deployment. Then someone builds something. They do not read the policy, not out of defiance, but because it is in a wiki they have never opened and they are trying to solve a problem today. Nothing in the path they took mentions the policy, and nothing checks. The policy is now a statement about intent. It is not a control, and treating it as one is how organizations end up genuinely surprised by their own systems. The test: for each rule in your AI policy, name the mechanism that enforces it. Rules with no mechanism are aspirations, which is fine as long as everyone knows which ones those are. ## Encode it where the action happens Each rule has a natural enforcement point, and it is usually somewhere in a letter of the surface rather than in a governance system. | Policy | Enforcement point | |---|---| | Only approved models | The [routing](/control/routing/) layer, by classification | | No customer data to unapproved endpoints | Routing plus redaction at the gateway | | Customer-facing deployments get review | [Ingress](/control/ingress/): public exposure is a gate | | Agents cannot write to production without approval | Tool permissions and a broker, in [Run](/run/secrets/) | | Retention limits | Lifecycle policy on the store, in [Control](/control/storage-and-backups/) | | Spend limits | Quota at the gateway, in [cost](/secure/cost/) | None of those live in a governance tool. That is the point: governance is a property of the platform, expressed in the places where things actually happen. A governance tool is useful for recording what the rules are and demonstrating they were followed. It cannot make them true. ## Decide the small number of things that need deciding Governance discussions expand indefinitely if nobody bounds them. The decisions that actually block work are few: 1. **Which data classifications may reach which endpoint types.** The single most consequential decision, and the one that unblocks the most work once made. 2. **What requires human approval before it executes.** Should be a short list. 3. **What may be customer-facing, and who signs.** 4. **What autonomy an agent may have**, expressed as tool permissions rather than adjectives. 5. **What must be retained, and for how long.** Five decisions, written down, with enforcement points named. That is a working AI governance position, and it fits on a page. ## Approval fatigue is a real failure mode A human-in-the-loop control is useful in proportion to how rarely it fires. An approval prompt on every action is trained away within a week: people click through it without reading, and you have added latency while removing nothing. Reserve approvals for actions that are irreversible, externally visible, or expensive. Everything else should be permitted and recorded, with the review happening after the fact on a sample. {{< aside title="How GRC thinks about this" >}} The GRC discipline separates control design from control operation, and tests both: does the control address the risk, and did it actually run. AI programs typically have neither answer, because the control is a policy document and its operation is unobservable. The useful move is to write each control as a testable assertion about a system, then let [Observe](/observe/) produce the evidence continuously. That also happens to be what makes an audit cheap. {{< /aside >}} {{< failure id="mchire" >}} {{< checklist >}} - For each rule in your AI policy, name the mechanism that enforces it. - Which data classifications may reach which endpoints, and what checks? - What actions require human approval, and how often does that approval get clicked through without reading? - Who signs off on a customer-facing AI deployment, and what do they see? - If an engineer wanted to break the policy today, what would stop them? - When was the policy last changed in response to something you learned? {{< /checklist >}} ================================================================ # Metrics URL: https://brocs.fyi/observe/metrics/ Summary: Golden signals plus the AI signals: tokens, cost, tool calls, and refusal rate, attributed per app, per team, and per user. Metrics are the numbers that tell you whether an AI system is working, and for whom. The existing four golden signals still apply. They are no longer sufficient. ## The four you already have Latency, traffic, errors, and saturation. Keep all of them, with two amendments. **Latency needs percentiles and a time-to-first-token.** A streaming response that starts in 400 milliseconds and finishes in nine seconds is a good experience. One that starts in eight seconds and finishes in nine is not, and total latency cannot tell them apart. **Saturation means someone else's limit.** The constrained resource is usually a provider rate limit or a token-per-minute quota you do not control. Track headroom against it, because the failure mode is a wall rather than a slope. ## The ones that are new **Tokens in and out, per request.** The base unit. Everything about cost and most things about latency derive from it. **Cost, attributed.** Not the monthly invoice. Cost per request, aggregated by application, team, and user. This is the number that makes every conversation in [Secure](/secure/cost/) possible, and it can only be collected at the point of inference. **Tool calls per session.** For agents, the strongest single indicator of health. A task that used to take four tool calls and now takes nineteen has degraded, and it will show up here before it shows up in a complaint. **Refusal and failure rate.** How often the model declines, returns malformed output, or fails schema validation. A rising refusal rate usually means a prompt, a policy, or a provider changed underneath you. **Retry rate.** Retries are where cost blows up quietly. An agent in a loop is a budget event. **Cache hit rate**, if you use prompt caching. It moves cost by large multiples and it degrades silently when a prompt prefix changes. ## Attribution is the design decision The single most consequential choice in AI observability is whether every inference call carries an identity: which application, which team, which user, which session. Add it at the start and every later question is answerable. Add it later and you are retrofitting identity into call sites across the estate, which in practice means it does not get added and cost stays a single line on an invoice. This is the payoff for routing model access through a gateway rather than distributing provider keys. See [keys and models](/build/keys-and-models/). ## Expose it to the people who own the thing Central dashboards are necessary and insufficient. The person who built an internal tool should be able to see their own tool's usage, cost, and error rate without asking the platform team, in the same way they can see its logs. Two reasons. The obvious one is that they will notice a problem faster than a central team watching two hundred services. The less obvious one is that visible cost changes behaviour: a builder who can see that their nightly job costs 300 dollars a month will usually fix it without anyone opening a conversation about it. {{< aside title="How SRE thinks about this" >}} The SRE discipline separates the signals users feel from the signals operators care about, and insists the first set drives the alerts. Applied here: tokens and cost are operator metrics, and they should not page anyone. Time-to-first-token, error rate, and task completion rate are user metrics, and those are the ones that belong in an objective. The trap is building a beautiful token dashboard and never measuring whether the thing actually worked. {{< /aside >}} ## The metric that is hardest and matters most Task success rate. Did the thing the user wanted actually happen. It is hard because it usually requires either an explicit signal from the user, an implicit one such as whether they retried or abandoned, or a judgement call from an evaluator. It is worth the effort because every other metric on this page can look healthy while the system is useless. {{< checklist >}} - Can you produce cost for one application, last month, without asking a vendor? - Does every inference call carry an application, team, and user identity? - What is your time-to-first-token at the 95th percentile? - Do you track tool calls per agent session, and do you know what normal looks like? - Can a builder see their own application's metrics without filing a request? - What is your task success rate, and if you cannot answer, what would it take? {{< /checklist >}} ================================================================ # Runtime URL: https://brocs.fyi/run/runtime/ Summary: Where AI apps and agents actually execute. Containers, functions, and jobs, and why the interesting workload is the long-running one. Runtime is the answer to "where does this thing execute". For a chat interface that question is boring. For an agent that runs for forty minutes, calls tools, writes files, and needs a credential the whole time, it is the question that decides whether the project is real. ## Three shapes, and only one of them is new **Request-response services.** A user asks, the app calls a model, the app answers. This is a normal web service and your existing platform already knows how to run it. Nothing here is special except token latency, which mostly means longer timeouts and streaming. **Batch and scheduled jobs.** Classification over a corpus, nightly summarisation, enrichment pipelines. Also solved: this is a job runner, and the AI part is a step inside it. **Long-running agents.** This is the one that breaks existing platforms. An agent session is stateful, lives for minutes or hours, holds credentials for that whole period, executes code, writes to a filesystem, and can be interrupted and resumed. It is closer to a developer workstation than to a web request, and platforms built around stateless twelve-factor services have nowhere natural to put it. Most organizations discover this by trying to run an agent on their existing serverless platform and hitting a timeout limit, then quietly moving it to somebody's VM. That VM is now production infrastructure with no owner. ## What an agent runtime actually needs Working through the requirements honestly gives a short and demanding list: - **A filesystem** that survives the length of a session and is destroyed after it. - **Execution isolation** strong enough that generated code cannot reach the host or other tenants. The threat model here is not a malicious insider; it is a model that read a web page containing instructions. - **Egress control.** An agent with unrestricted outbound network access can exfiltrate anything it can read, and it does not have to be compromised to do it, only confused. - **Credential injection at runtime**, scoped to the session, expiring with it. See [secrets](/run/secrets/). - **Interruptibility.** A human needs to be able to stop it, and stopping it has to actually stop it rather than orphan the work. - **A record of what it did**, emitted as it goes. See [traces](/observe/traces/). Notice how many of these are boundaries rather than capabilities. The runtime's job is mostly to be a box with well-understood walls. ## Blast radius is a runtime property The most consequential runtime decision is what the executing code can reach. It is worth writing down explicitly for each workload, because the default answer is almost always "more than you think": the network the container sits on, the cloud role attached to it, the databases reachable from that network, and any credential in its environment. An agent that can write to production because it happens to run on a host with a production role is a design decision nobody made. {{< failure id="replit-prod-db" >}} ## Internal alternatives to the platforms people actually like There is a reason developers reach for Railway, Render, Heroku, or a cloud's app service: those products answer "where does it run" with one command and no meeting. If your internal answer is a Kubernetes namespace request form, people will keep reaching. The realistic goal is not to build a better cloud. It is to present the same small interface over whatever you already run: push, get a URL, get logs, get a database, get a secret. Underneath it can be Kubernetes, ECS, VMs, or all three. The interface is the product; the substrate is an implementation detail, and treating it that way is what makes [portability](/run/portability/) possible later. {{< aside title="How SRE thinks about this" >}} An SRE will ask what happens when the model provider is slow, not when it is down. Degraded is the common case: latency doubles, a fraction of requests fail, and retries turn a provider hiccup into a self-inflicted load spike. Timeouts, budgets, circuit breakers, and bounded retries are the same tools as always, and they matter more here because the dependency is slower and less predictable than a database. {{< /aside >}} ## Multi-tenancy is not optional Even inside one company, AI workloads are multi-tenant: different teams, different data classifications, different model access. A runtime that assumes everything on it is equally trusted will eventually put a finance agent and a public-facing chatbot on the same host with the same egress. Decide early which boundary carries the isolation: namespace, node, account, or cluster. Changing that decision later is a migration. {{< checklist >}} - Where does a long-running agent execute today? Name the machine or the platform. - What can that runtime reach: which network, which cloud role, which databases? - If generated code tried to make an outbound connection to an arbitrary host, what stops it? - Can a human stop a running agent, and does stopping it release its credentials? - What happens to the agent's filesystem when the session ends? - Which teams share a runtime boundary, and is that deliberate? {{< /checklist >}} ================================================================ # The BROCS assessment URL: https://brocs.fyi/resources/assessment/ Summary: Twenty statements, four per letter. Score the ones that are true today and you get a scoreline. Check every statement that is true of your organization **today**. Not planned, not in someone's roadmap, not true for one team that figured it out on their own. True. Your score for each letter is the number of statements you could check, so each letter lands between 0 and 4 and the whole thing reads as a scoreline: `B3 R2 O1 C2 S0`. Nothing is stored and nothing is sent anywhere. The scoreline lives in the URL, so the link is the result: send it to whoever needs to see the gap. ================================================================ # Tooling URL: https://brocs.fyi/build/tooling/ Summary: The enablement layer beneath IDEs, agent CLIs, notebooks, and chat. How to survive tool churn without re-platforming every year. Tooling is the set of interfaces through which people in your organization do AI work: IDEs and their assistants, agent CLIs, notebooks, chat surfaces, and low-code builders. The Build question is not which of these is best. It is what sits underneath all of them, and whether that layer is yours. ## The churn is the design constraint Name the AI coding tool your engineers used eighteen months ago. Now name the one they use today. For most organizations those are different answers, and there is no reason to expect the next eighteen months to be calmer. This is normally treated as a procurement annoyance. It is actually an architecture requirement. If identity, key distribution, data access, and runtime are configured inside a specific tool, then adopting the next tool means redoing all four, and the organization quietly develops a preference for whatever it already has. That preference is not a considered decision. It is switching cost pretending to be strategy. The alternative is an enablement layer that the tools plug into rather than the other way round. Identity comes from your identity provider. Keys come from your key service. Data access goes through your gateway. Execution happens in your runtime. The tool becomes a client, and a client is replaceable. ## What belongs in the layer, not the tool Five things, and it is worth being strict about them. **Identity.** The tool authenticates the person against your IdP. It does not hold its own user list, and it does not have a separate concept of a team. **Model credentials.** The tool receives a scoped, short-lived credential, or it talks to a gateway that holds the real key. It never sees a long-lived provider key, and it is never the thing that decides which model is allowed. **Data access.** The tool reaches data through an interface that already knows who the user is and what they are allowed to see. Handing an assistant a database URL and trusting the prompt is not access control. **Execution.** Anything that runs code, installs packages, or touches infrastructure runs somewhere you chose, with the permissions you granted. See [Run](/run/). **Telemetry.** Usage, cost, and traces flow to your observability stack, not only to the vendor's dashboard, which you will lose access to the day you stop paying. See [Observe](/observe/). If those five are yours, a tool migration is a configuration change and a training session. If any of them lives inside the tool, it is a project. ## Desktop tools, remote capability A common false choice: either people work locally and lose access to shared compute, data, and long-running agents, or everything moves to a browser and you fight the developers who are faster in their own editor. The resolution is that a desktop tool can drive remote capability. The editor stays local; the agent runs on a machine you control, with the data mounted and the credentials injected there. Nothing sensitive lands on the laptop, and the workflow is still the one people already know. Getting this right is mostly about the execution and credential boundaries above, not about the editor. ## Standardize the interface, not the vendor The useful standardization target is the shape of the integration: how a tool discovers what data and actions it may use, how it authenticates, and how it reports what it did. Where an open protocol exists for that shape, prefer it, because it is what makes the next tool a drop-in. Standardizing the vendor instead produces the outcome the framework is arguing against: a single supplier holding your identity, your keys, your data path, and your runtime, with a switching cost that grows every quarter. {{< aside title="How platform engineering thinks about this" >}} A platform team's instinct is to build the paved road and let teams choose their own boots. Applied here: the platform owns identity, credentials, data access, runtime, and telemetry, and stays deliberately uninterested in which editor you like. The failure mode platform teams already know is building the road around one vendor's boots, then discovering the vendor changed the sole. {{< /aside >}} ## Tooling is a supply chain An agent CLI or an editor extension is executable code with network access and, usually, your credentials. It deserves the same provenance questions as any other dependency: who publishes it, who can merge to it, is the version pinned, and what happens on auto-update. There is a newer wrinkle. Prompts are now part of the shipped artifact, and a prompt is an instruction to something that can act. Review processes built to read a code diff will skim a text file. {{< failure id="amazon-q-wiper" >}} {{< checklist >}} - If we replaced our primary AI coding tool next quarter, what would we have to rebuild? Name the systems, not the effort. - Where does this tool get the user's identity? If the answer is "its own account", who deprovisions it when someone leaves? - What model credential does the tool hold, and how long does it live? - Does anything this tool does show up in our telemetry, or only in the vendor's console? - Which extensions and agent CLIs are installed across the fleet right now, at which versions, and who can merge code into them? - When the tool auto-updates, what reviewed it? {{< /checklist >}} ================================================================ # Access URL: https://brocs.fyi/build/access/ Summary: Identity for builders: who gets which AI tools, how they authenticate, and how a new hire is productive on day one. Access is the question of who in your organization can build with AI, through what identity, and how long it takes them to start. It is the least glamorous part of Build and the one that most reliably determines whether anything else happens. ## Day one is the metric The honest measure of the Build surface is how long it takes a new person to ship something small and real. Not to get a login. To ship. In organizations that have not built the enablement layer, that number is usually measured in weeks and is composed almost entirely of waiting: waiting for a tool license, waiting for an API key, waiting for access to a dataset, waiting for someone to explain which of the three internal wikis is current. None of that is work. It is queue. The DORA program made lead time for changes a standard metric because it correlates with almost everything else that matters. Lead time from idea to running is the same metric pointed at a different population, and the AI version is worse than the software version in most organizations because the paths are newer and less paved. ## Role-based grants, not per-person heroics The pattern that scales is boring: define a small number of builder profiles, attach tool and data grants to the profile, and assign people to profiles through the same group membership that governs everything else. Three profiles cover most organizations to start: - **Engineer.** Full agent tooling, sandboxed execution, access to non-production data by default, production data by exception and with approval. - **Analyst or business builder.** A supported low-code or notebook path, access to the data domains their role already covers, no ability to grant themselves more. - **Reviewer.** Read access to what others have built, plus the ability to approve the exceptions. The point of profiles is not the taxonomy. It is that adding the fourth profile is a decision someone makes deliberately, rather than the natural result of forty individual exceptions nobody can reconstruct. ## The exception path is the real policy Every organization has a rule that says production data requires approval. What distinguishes the ones where the rule holds is that the approved path is fast enough to use. If approval takes four days and the workaround takes four minutes, you have not implemented a control, you have implemented a measurement of how much people care. Make the exception path short, logged, and time-bound. An approval that grants access for a week and then expires is worth more than one that grants access forever and gets reviewed annually. {{< aside title="How identity teams think about this" >}} Nothing here is new to an identity practitioner: groups, entitlements, joiner-mover-leaver, time-bound elevation. The amendment is that AI tools multiply the number of places a standing credential can hide, and several of them are consumer products bought on a personal card. If deprovisioning does not reach those, the leaver process has a hole in it that the offboarding checklist will not show. {{< /aside >}} ## What happens when access is missing People do the work anyway. They sign up for a personal account, paste in what they need, and get on with their job. This is usually described as a discipline problem. It is better understood as a routing problem: demand exists, the sanctioned path does not, so the demand finds another path. Cisco's 2024 Data Privacy Benchmark Study, a survey of 2,600 privacy and security professionals, found that 48 percent of organizations admitted entering non-public company information into generative AI tools, while 27 percent had banned the tools at least temporarily. Both numbers describe the same gap from different sides. The practical consequence is that Access is not only a Build concern. Every month the sanctioned path is missing is a month of accumulating [shadow AI](/secure/shadow-ai/), and that is a Secure problem you will inherit later at a worse exchange rate. {{< checklist >}} - How long from a new hire's start date to their first working AI change in production? Measure it on the next hire rather than estimating. - Which AI tools does someone get automatically by being in a group, and which require a ticket? - When someone leaves, what deprovisions their AI tool access? List the systems. - What is the approved path to production data, and how long does it take end to end? - How many standing exceptions exist right now, and when were they last reviewed? - Can a non-engineer get to a supported build path without knowing an engineer personally? {{< /checklist >}} ================================================================ # Agents URL: https://brocs.fyi/secure/agents/ Summary: What are the agents up to: tool permissions, audit trails, and human oversight that survives contact with volume. An agent is a model with tools and a loop. The tools are the part that matters: an agent without tools produces text, and an agent with tools produces consequences. ## Blast radius, written down The most useful artifact for any agent is a short document listing what it can reach: - **Tools**, with the operations each one permits. Not "database access" but "read from these tables". - **Identity**, meaning what it acts as and what that identity is allowed to do everywhere, not just here. - **Data**, meaning what it can read at all, including anything reachable through its tools. - **Network egress**, meaning where it can send bytes. - **Cost ceiling**, meaning what it can spend before something stops it. Most organizations have never written this down for any agent, and the exercise is uncomfortable in a useful way. The common discovery is that an agent built to do one narrow thing runs with credentials that permit a great deal more, because scoping precisely was more work than the task seemed to justify. ## Untrusted input is the whole problem The security model of a normal application assumes instructions come from code and data comes from users. An agent reads data and treats it as instructions, which collapses the distinction. Every document, ticket, email, web page, and search result an agent reads is a potential instruction to it. This is not theoretical. {{< failure id="echoleak" >}} The practical consequences: **Separate the reading from the acting.** A component with broad read access should not also hold broad write access. If it must, the writes should go through a broker that validates them independently of the model's reasoning. **Constrain the tools rather than the prompts.** Instructions telling a model to ignore malicious content are a mitigation, not a control. What actually bounds the damage is that the tool cannot do the dangerous thing. **Treat egress as a security boundary.** Exfiltration needs a path out. An agent that can only reach a fixed set of hosts cannot send your data to an arbitrary one, regardless of what it was persuaded to do. ## Audit trails an auditor would accept The [trace](/observe/traces/) is the raw material. The audit trail is what you can hand someone: for a given action, who or what did it, on whose behalf, when, with what authorization, and what changed. Two properties make the difference. It has to be **tamper-evident**, meaning the agent cannot edit its own record. And it has to be **queryable by subject**, meaning you can ask what happened to this customer's record rather than only what happened in this session. Most agent frameworks produce logs. Logs are not an audit trail until someone can answer those questions from them without writing a script. ## Human oversight that scales "Human in the loop" as a phrase covers three different things, and it is worth naming which you mean: - **Approval before action.** Strong, expensive, only viable on a small set of actions. - **Review after action.** Sampled, cheap, catches systematic problems rather than individual ones. Underused. - **Interrupt during action.** A person can stop a running agent. Requires that stopping actually stops it, which is a [runtime](/run/runtime/) property. Most organizations implement the first, on too many actions, and neither of the others. Sampled review after the fact is the highest-value thing most teams are not doing. {{< checklist >}} - For your most autonomous agent, list its tools, identity, data reach, egress, and cost ceiling. Can anyone produce that today? - What untrusted content does that agent read, and what stops instructions inside it from being followed? - Can the agent reach an arbitrary host on the internet? - For an action it took last week, can you produce who, on whose behalf, when, and under what authorization? - Can a human stop a running agent, and does it release its credentials when stopped? - Who reviews a sample of agent actions after the fact, and how often? {{< /checklist >}} ================================================================ # Data and state URL: https://brocs.fyi/run/data-and-state/ Summary: Databases, object storage, vector indexes, and session state for AI workloads: provisioned on demand, owned, and backed up. Every AI application accumulates state faster than its builders expect. Conversation history, uploaded documents, generated artifacts, vector indexes, evaluation results, and the prompt log. Most of it appears without a provisioning request, because it started as a file on a laptop. ## The stores you will end up with **A primary database.** Ordinary application data, and the one people remember to ask for. **Object storage.** Uploads and generated files. Usually the first store to be created by hand, and often the one with the most permissive access policy in the estate, because a builder needed a URL that worked. **A vector index.** A copy of your documents, chunked, with the original text usually stored alongside the embeddings. This is the store most likely to be missing from your data catalogue while containing the most sensitive material. See [data access](/build/data-access/). **Session and conversation state.** Often in whatever cache was nearest. Frequently contains full prompt and response history, including whatever a user pasted in. **The prompt log.** Discussed in [Build](/build/data-access/); repeated here because teams reliably forget it is a data store with a retention obligation. Each needs the same four properties as any other production store: an owner, a classification, a backup, and a retention period. The failure mode is not that these are hard. It is that they were created outside the process that would have asked. ## Provisioned, not hand-built A store created by a person in a console has no template, no tags, no backup policy unless they remembered, and no reproducibility. A store created by the platform has all four because they were decided once. This is the strongest argument for self-service [provisioning](/run/provisioning/): not speed, though it is faster, but that the defaults come along for free. The team asking for a database should not have to know your backup standard in order to comply with it. ## Backups you have actually restored The uncomfortable question is not whether backups run. It is whether anyone has restored one. For AI workloads there are two specific traps. The first is that the vector index is often treated as a derived artifact that can be rebuilt, right up until you discover rebuilding takes eleven hours and costs real money in embedding calls. The second is that conversation history is frequently the only record of what a system told a user, which makes it evidence as well as data. Schedule a restore drill. Put it in the calendar with a name attached. An untested backup is a belief, not a control. {{< aside title="How data engineering thinks about this" >}} A data engineer will ask about lineage first: where did this index come from, what produced it, and what happens when the source changes. That framing is the right one. A vector index is a materialised view over governed data, and the questions that apply to any materialised view apply here: freshness, invalidation, permission inheritance, and deletion propagation. {{< /aside >}} ## Deletion has to propagate When a customer asks to be deleted, or a document is withdrawn, the record has to leave every copy: primary database, object storage, vector index, conversation history, prompt log, and any backup you keep long enough for it to matter. Most AI stacks fail this test on at least two of those, usually the index and the log. Working out the answer before someone asks is considerably cheaper than working it out during a regulator's timeline. {{< checklist >}} - List every store your AI applications write to. Does the list include the vector index and the prompt log? - Which of those stores has a named owner and a classification? - When did you last restore one of them, on purpose, as a drill? - If a document is deleted from the source system, what removes it from the index, and how long does that take? - How much would it cost, in time and money, to rebuild the vector index from scratch? - Who can read the conversation history table today? {{< /checklist >}} ================================================================ # Failure-mode library URL: https://brocs.fyi/resources/failure-modes/ Summary: Public AI incidents, each mapped to the letter that was skipped, each with a source you can check. Every entry here is a public incident with at least one source you can go read. Each one is mapped to the letter of the surface that was missing, because the useful pattern is not "AI is risky", it is "this specific gap produces this specific outcome, repeatedly". Two things worth noticing as you read. First, almost none of these are model failures. The model did roughly what a model does; the surface around it was missing a boundary, a control, or a pair of eyes. Second, the same incident usually maps to more than one letter, because a gap in one letter is normally what made the gap in another letter matter. ================================================================ # Ingress URL: https://brocs.fyi/control/ingress/ Summary: One front door for internal AI applications, instead of a tunnel, a share link, and a forwarded port per team. Ingress is how a request reaches an internal application, and where authentication, authorization, and logging get applied. It is a solved problem that AI adoption reliably unsolves, because the shortest path from a working prototype to a colleague trying it is a public URL. ## How the sprawl happens Someone builds a useful tool. They need to show it to three people. The options are the platform's ingress process, which takes a few days, or a tunnel from their laptop, which takes ninety seconds. Three months later that tunnel is load-bearing, it runs from a machine under a desk, it has no authentication beyond an unguessable hostname, and the person who set it up has changed teams. Multiply by the number of enthusiastic builders in your organization. The lesson is the one from [Build](/build/idea-to-production/): the sanctioned path has to be faster than the workaround. An ingress request that resolves in a day loses to a tunnel that resolves in a minute, every time, regardless of policy. ## What one front door gives you Routing every internal AI application through a single ingress layer means these are solved once instead of per application: - **Authentication.** SSO by default, with no application implementing its own login. - **Authorization.** Group-based access enforced before the request reaches the app. - **Logging.** Who reached what, when, from where. Frequently the only access record that exists for a tool built in an afternoon. - **Rate limiting.** Both abuse protection and a spend control, since every request behind it costs money. - **TLS and certificates.** Not per team, and not expired. - **A kill switch.** One place to cut off an application that is misbehaving, without finding whoever owns it. The kill switch matters more than it sounds. When an internal tool starts doing something wrong, the response time is bounded by how quickly you can stop it reaching users. ## Public exposure is a different decision Internal ingress should be self-service. Public exposure should not be. The moment an AI application is reachable by people outside the organization, several things change at once: the input is untrusted, the output is a public statement by your company, and the cost is driven by strangers. All three need a deliberate decision by someone accountable, plus rate limiting, abuse handling, and a review of what the application can reach. Make internal easy and public a gate. Most organizations get this backwards by having one process for both, which is either too slow for internal use or too loose for external. {{< failure id="air-canada-chatbot" >}} ## Partners and contractors without VPN sprawl The requirement that breaks naive designs is external collaborators who need access to some internal applications and nothing else. The pattern that works is federation at the ingress layer rather than accounts in your directory: the partner authenticates against their own identity provider, your ingress maps that to a scoped role, and access is time-bound. No VPN, no guest accounts that outlive the engagement by three years. The pattern that does not work, and is extremely common, is a shared credential in an email. {{< aside title="How zero trust thinks about this" >}} The zero trust position is that network location is not authorization, and every request gets authenticated and authorized on its own. Internal AI tools are a good test of whether you actually believe that: they are usually built quickly, hosted internally, and treated as safe because they are behind the perimeter. An identity-aware proxy in front of every internal app, including the ones built by non-engineers, is the practical expression of the idea. {{< /aside >}} {{< checklist >}} - How many internal AI applications are reachable right now, and through what? - How long does it take to get a hostname with SSO in front of it? - Is there a tunnel running from someone's laptop that people depend on? - Can you cut off one application in under five minutes without finding its owner? - What is the process for making an AI application public, and who signs it? - How do external collaborators reach the applications they need? {{< /checklist >}} ================================================================ # Traces URL: https://brocs.fyi/observe/traces/ Summary: Reconstructing what an agent did: prompts, tool calls, arguments, results, and the data it touched. A trace is the ordered record of what happened inside one run. For a service, it is spans across components. For an agent, it is the sequence of reasoning steps, tool calls, arguments, results, and data touched, from the request to the final answer. It is the artifact you need when someone asks what happened. It is also the artifact an auditor will ask for, which makes it the most direct overlap between [Observe](/observe/) and [Secure](/secure/). ## What a usable agent trace contains - **The triggering input**, including who or what supplied it. - **Each model call**: the model and version, the resolved prompt, the completion, the token counts, and the latency. - **Each tool call**: the tool, the arguments, the result or error, and the identity the call was made under. - **Every document retrieved**, with an identifier stable enough to find it again. - **Decision points**: where the agent chose between options, and what it had available. - **The terminal state**: completed, failed, stopped by a human, or abandoned on a timeout. The test is whether a competent colleague, with no memory of the incident, can read the trace and say what the system did and why. If they have to guess at a step, that step is missing. ## Tool calls are the part that matters Model reasoning is interesting. Tool calls are consequential. The tool call is where the agent stops producing text and starts changing the world: writing a row, sending a message, opening a ticket, deploying something. So if you can only instrument one thing, instrument tool calls with full arguments, results, and the identity used. That gives you the answer to "what did it actually do", which is the question that gets asked in incidents and audits, and it is a shorter path than capturing every token. Two cautions. Arguments frequently contain credentials or personal data, so redact on the way in rather than at query time. And record the identity the call was made under, not just the tool name, because "the agent updated the record" and "the agent updated the record as the finance service account" are very different sentences. ## Sampling, retention, and the honest trade Full-fidelity traces on every request get expensive quickly, particularly when you are storing prompts and completions. A workable policy: - **Sample the routine.** A small percentage of successful, low-risk sessions. - **Keep everything abnormal.** Errors, human interventions, anything that touched production, anything above a cost threshold, anything a user flagged. - **Keep tool calls at full fidelity even when you sample the reasoning.** They are small and they are the evidence. - **Set retention by what it contains**, not by what it is. A trace holding personal data inherits that data's retention rules, and pretending it is telemetry does not change that. ## Correlation across the boundary An agent trace that stops at the tool call boundary is half a story. The tool call hit a service, that service hit a database, and the interesting failure is often on the far side. Propagate a trace identifier from the agent through every tool call into the downstream systems, using whatever standard you already use. It is a small amount of plumbing and it converts two separate investigations into one. {{< failure id="cursor-support-bot" >}} {{< aside title="How observability practitioners think about this" >}} The distributed tracing discipline arrived at a settled answer: one trace identifier, propagated everywhere, with spans that nest. Agents fit the model without modification; a tool call is a span and a sub-agent is a child trace. The reason AI stacks so often end up with a parallel, incompatible tracing system is that agent frameworks ship their own, and nobody wires it to the existing one. That is an afternoon of work with a large payoff. {{< /aside >}} {{< checklist >}} - For an agent run last Tuesday, can you list every tool it called and with what arguments? - Do traces record the identity each tool call was made under? - What redacts credentials and personal data from tool arguments before storage? - Does your agent trace share a trace identifier with your existing service tracing? - What is the retention period on traces, and does it reflect what they contain? - Which sessions do you keep at full fidelity, and who decided that list? {{< /checklist >}} ================================================================ # Alerts URL: https://brocs.fyi/observe/alerts/ Summary: Routing alerts to the builder who owns the application, not only to a central operations queue. An alert is a claim that a human needs to do something now. Most AI monitoring produces the opposite: dashboards nobody watches and thresholds that fire into a channel with four hundred members. ## Route to the owner, not the centre The organizing principle is that the alert goes to whoever can fix the thing. For an internal tool built by an analyst, that is the analyst. For a shared inference gateway, that is the platform team. This sounds obvious and is rarely implemented, because AI applications frequently arrive without an owner field. Somebody built it, it works, it is in production, and the monitoring defaults route to the platform team because that is where monitoring lives. The platform team then receives alerts about applications they did not build, cannot change, and do not understand. They triage by forwarding. Everyone learns the alerts are not actionable, and the next real one is missed. Fix it at provisioning time: an application without a named owner does not get created. See [idea to production](/build/idea-to-production/). ## What is worth waking someone for Three categories, and it is worth being ruthless about the boundary. **Page a human.** The system is failing users right now and a person must intervene: sustained error rate, provider outage with no fallback, an agent stuck in a loop burning budget, a security control that failed open. **Ticket for the morning.** Something is wrong but tolerable: elevated refusal rate, a cost anomaly within the budget, a single failed evaluation, rising latency with no breaches. **Dashboard only.** Everything else. Token counts, cache hit rates, and volume are context during an investigation, not events. Most organizations put the second category in the first, discover the pager is noisy, and then stop trusting it. Moving things down is harder than never putting them there. ## AI-specific alerts worth having - **Cost rate of change.** Not a monthly total. A sudden step in spend per hour catches a retry loop in minutes rather than at invoice time. - **Agent session duration outliers.** A session running four times longer than the median is usually stuck, and it is usually still spending. - **Refusal or schema-failure spike.** Almost always means something upstream changed: a prompt, a policy, a model version. - **Eval regression on the pinned suite.** The closest thing to a quality alert. See [model behaviour](/observe/model-behavior/). - **Guardrail trips.** If a filter or policy check starts firing at ten times its baseline, someone is probing or something broke. - **Silence.** A scheduled AI job that produced no output is a failure that looks like nothing. Alert on absence. ## The alert that should exist and usually does not Quality degradation reported by a human. Give users a one-click way to flag a bad response, route those flags somewhere a person reads, and treat a cluster of them as an incident signal. It is unfashionable because it is not automated. It is also, in most organizations, the fastest detector you have for the failure mode traditional monitoring cannot see: a system returning 200s with worse answers than last week. {{< aside title="How on-call practice thinks about this" >}} The settled wisdom is that every page must be actionable, novel, and urgent, and that alerts which do not meet the bar should be deleted rather than muted. The AI amendment is that a whole class of real failures is not detectable by threshold at all, which means the alert has to come from an eval, a canary, or a user. Building those signals is the work; tuning thresholds is not. {{< /aside >}} {{< checklist >}} - For each AI application in production, who gets paged? Name them. - How many AI alerts fired last month, and how many resulted in an action? - Do you alert on cost rate of change, or only on totals? - What happens when a scheduled AI job produces nothing at all? - Can a user report a bad response in one click, and where does that go? - Is there an alert that would have caught your last AI incident? If not, is there one now? {{< /checklist >}} ================================================================ # Glossary URL: https://brocs.fyi/resources/glossary/ Summary: The BROCS vocabulary, defined tersely and linkably. Definitions, not arguments. Each term is a stable anchor you can link to, and the whole set is published as structured data so answer engines can quote it without paraphrasing it into something else. ================================================================ # Identity URL: https://brocs.fyi/control/identity/ Summary: SSO for every internal AI app by default, and access for partners and contractors that expires. Identity is the question of who is making a request, carried consistently from the person at the keyboard through every layer to the data. In AI systems it usually survives the first two hops and then gets replaced by a service account, which is where the interesting problems start. ## Identity has to survive the whole path The chain that matters: 1. A person authenticates to an application through SSO. 2. The application calls a model through the gateway, carrying that person's identity. 3. The model requests data through a tool, and the tool applies that person's permissions. 4. The trace records which person the whole run was on behalf of. Break any link and you lose something concrete. Break the second and cost attribution becomes impossible. Break the third and you have built a system where the model's permissions are the union of everyone's. Break the fourth and you cannot answer who asked for this. Link three is the one that breaks most often, because passing user context through a tool call is more work than giving the tool a service account with broad access. The consequence is a system where any user can, in principle, be shown any data the service account can read. ## Agents need identities of their own An agent acting autonomously, on a schedule with no user attached, still needs to be someone. Giving it a human's credentials is the reflex and it is wrong: it inherits permissions nobody scoped, it breaks when the human leaves, and every trace says a person did something they were asleep for. Give the agent a workload identity with its own permissions, and record both identities when it acts on someone's behalf: the agent, and the human who asked. "The reconciliation agent, on behalf of Priya, updated the record" is the sentence you want, and it needs two identities to be true. ## Joiner, mover, leaver, and the AI estate The offboarding process at most organizations covers the systems that existed when it was written. AI adoption adds several that were not on the list: the model provider console, the agent tooling, the vector database, prompt-editing surfaces, and any tool bought on a personal card. Two failure modes worth checking for. A leaver whose personal provider account still holds an organization key, and a mover whose access grew with each role and never shrank. The second is the more common and the more expensive: after three internal moves, a person holds the union of three roles, and any agent acting on their behalf inherits it. {{< aside title="How identity practitioners think about this" >}} The mature version of this is the least-privilege lifecycle: entitlements attached to roles, roles attached to people through groups, periodic recertification, and just-in-time elevation for the rest. None of it is new. The AI amendment is that agents are a new principal type that acts continuously and on behalf of others, so the delegation model, not just the permission model, has to be explicit. {{< /aside >}} ## Service accounts are where governance goes to die Every AI stack accumulates them: one for the indexer, one for the batch job, one for the tool that needed database access. Each was created for a good reason and scoped generously because scoping precisely was fiddly. Two rules keep this manageable. Every service account has a named human owner and an expiry date on its review, not on itself. And no service account is shared between two applications, because the moment it is, neither can be scoped down without breaking the other. {{< checklist >}} - When an AI application reads data, whose permissions apply? - Does every agent have its own identity, distinct from the person who runs it? - For an autonomous agent action last week, can you name both the agent and the person it acted for? - What does your leaver process do about model provider accounts? - List your AI service accounts. Who owns each, and when were they last reviewed? - Is any service account used by more than one application? {{< /checklist >}} ================================================================ # Keys and models URL: https://brocs.fyi/build/keys-and-models/ Summary: Distributing, scoping, rotating, and metering model credentials. BYOK, local models, models through your own cloud, and BAA-covered endpoints. A model API key is a bearer credential with a billing account attached and, in most organizations, no expiry. It is the most casually handled secret in the building. ## The spreadsheet is the incident The common pattern goes like this. One team needs model access. Someone with a corporate card creates a provider account and generates a key. The key goes into a shared document so the rest of the team can use it. Six months later that document has been copied into two other teams, the key is in four repositories and a CI system, the person who created it has changed roles, and nobody can say what would break if it were rotated. That is not a security lapse by an individual. It is the predictable output of having no key distribution system, and the fix is not a training module. The fix is that keys are issued by something, scoped to something, and expire. Concretely: - **Nobody holds a provider key.** Applications and tools authenticate to an internal gateway with their own identity. The gateway holds the provider credential. - **Every call is attributable.** The gateway knows which app, which team, and which user made the request, because that is the only way [cost](/secure/cost/) and [traces](/observe/traces/) work later. - **Rotation is a routine operation.** If rotating the provider key requires a change window and a list of teams to notify, it will not happen. Behind a gateway it is one change in one place. - **Revocation is per-consumer.** Cutting off one misbehaving app should not take down everything else that shares the key. ## Four ways to get model access, and why you need more than one **Vendor SaaS endpoint.** Fastest to adopt, least control. Fine for a large class of internal work, and unacceptable for another class. The decision belongs to a policy, not to whichever engineer moved first. **BYOK.** Your provider credentials, your account, your billing, your data-processing terms, someone else's application. This is the pattern that lets a regulated organization use a third-party product without the product vendor becoming a processor of the underlying data. **Models through your own cloud.** The same model families served inside your existing cloud account, under the contract, network boundary, and audit regime you already have. For many enterprises this is the shortest path from "we cannot use that" to "we can use that", because it does not require a new vendor relationship at all. **Local or self-hosted models.** Slower and more work, and the only option when data genuinely cannot leave a boundary. Also the only option that is immune to a provider deprecating a model you depend on. Regulated work adds a fifth consideration: **BAA-covered endpoints**. If protected health information touches the model, the endpoint has to be covered by a Business Associate Agreement. Whether an endpoint is covered is a contractual fact, not a technical one, and it needs to be recorded somewhere the routing layer can read. Most organizations end up with three of these at once, which is exactly why the routing decision has to be centralized rather than made independently in each application. That is a [Control](/control/routing/) concern, and it is the payoff for doing keys properly. {{< aside title="How secrets management thinks about this" >}} A secrets practitioner will point out that everything above is standard: short-lived credentials, no long-lived bearer tokens in application config, per-consumer identity, central rotation. That is the point. Model keys have escaped the secrets discipline mostly because they arrived through product teams and corporate cards rather than through infrastructure. Putting them back under the existing regime is the whole task. {{< /aside >}} ## Metering is not billing Metering is knowing who spent what. Billing is deciding who pays. You need the first long before you need the second. Without metering, a surprising invoice produces a blunt response: a spend cap that stops everyone, or a policy that stops the experimentation you were trying to encourage. With metering, the response is proportionate, because you can see that one batch job is 80 percent of the bill. Meter at the gateway, on every call: model, tokens in and out, latency, app, team, user. Everything in [cost](/secure/cost/) depends on that record existing. ## What a key in the wrong place actually costs The risk is not only unauthorized spend. A leaked key is an authenticated path into your provider account, and provider accounts increasingly hold more than inference: fine-tuned models, uploaded files, assistant configurations, and logs of everything anyone sent. {{< failure id="deepseek-clickhouse" >}} {{< checklist >}} - How many provider API keys exist in the organization? If you cannot answer, that is the answer. - Can you rotate the primary provider key this afternoon without a change window? - For a single inference call last week, can you name the app, the team, and the user? - Which of the four access paths do you support today, and which are you one incident away from needing? - Where is it recorded that a given endpoint is BAA-covered, and does anything enforce it? - If a key leaked tonight, what else in the provider account would the holder reach? {{< /checklist >}} ================================================================ # Secrets URL: https://brocs.fyi/run/secrets/ Summary: Runtime secret injection for AI workloads. Never in code, never in a prompt, never in chat history. Secrets management for AI workloads is the existing discipline with two new leaks: the prompt and the trace. Everything else you already know how to do. ## The old rules still apply No secrets in source. No secrets in container images. No long-lived credentials where a short-lived one would work. Injection at runtime from a secret store, scoped to the workload identity. Rotation that does not require a change window. If your AI applications do not meet that bar, fix that first. It is not an AI problem and there is nothing novel about it. ## The two new leaks **The prompt.** People paste credentials into prompts. Not out of carelessness, usually: they are debugging a failing API call and they paste the whole request, header included. That prompt is now in the provider's logs, your prompt log, the conversation history table, and possibly a trace. One paste, five copies. **The trace.** An agent trace captures tool calls and their arguments, which is exactly what makes it useful and exactly what makes it dangerous. A tool call that authenticates will put the credential in the trace unless something redacts it. Both need the same treatment: detection and redaction on the way in, not a policy telling people not to do it. Pattern-match for known credential shapes at the gateway and at the trace collector, redact before storage, and alert when it happens so you can go fix the workflow that made it necessary. ## Agents hold credentials for a long time A web request holds a credential for milliseconds. An agent session holds one for the length of the session, in a process that is also executing generated code and reading untrusted content. That is a longer window and a worse neighbourhood. Three mitigations, in order of value: 1. **Scope down.** The credential the agent holds should permit exactly the operations the task needs, not the union of everything the team can do. 2. **Shorten.** Issue at session start, expire at session end. If a session outlives its credential, it should re-request rather than hold a long one. 3. **Broker instead of hand over.** The strongest pattern: the agent never holds a credential at all. It calls a broker that performs the privileged operation and returns the result. Then a compromised or confused agent can invoke an operation but cannot exfiltrate the key. The third is more work and it is the one worth building for anything touching production. {{< aside title="How secrets management thinks about this" >}} The workload identity model already solves this: a workload proves what it is, receives a short-lived credential scoped to that identity, and never holds a static secret. Agents fit the model cleanly. The reason they usually do not use it is that agent frameworks default to reading environment variables, and environment variables are where static secrets go to live forever. {{< /aside >}} ## Chat history is a secret store you did not design If your organization uses a chat interface to a model, assume credentials are in it. Assume the same for ticket comments, incident channels, and pull request descriptions, all of which now feed retrieval indexes at many companies. This is worth stating plainly because the mitigation is unglamorous: scan what you index, scan what you log, and rotate on detection. The alternative is to discover it during an audit, at which point the question is not whether it happened but for how long. {{< failure id="deepseek-clickhouse" >}} {{< checklist >}} - How does an AI workload get its model credential at runtime? If the answer is an environment variable set at deploy time, how long has that value been the same? - What scans prompts for credential patterns before they are stored? - Are tool-call arguments redacted in traces, and who verified that? - For a production-touching agent: does it hold the credential, or does a broker hold it? - If a credential leaked into chat history six months ago, would you know? - Does your secret rotation runbook include the model provider keys? {{< /checklist >}} ================================================================ # Shadow AI URL: https://brocs.fyi/secure/shadow-ai/ Summary: Discovering unsanctioned tools, and understanding why people reached for them in the first place. Shadow AI is the use of AI tools your organization has not sanctioned, usually through personal accounts and personal payment methods. It is normally framed as a discipline problem. It is better understood as a routing problem: demand exists, the sanctioned path is missing or slow, so the demand finds another path. ## The numbers, with sources Cisco's 2024 Data Privacy Benchmark Study, a double-blind survey of 2,600 privacy and security professionals across 12 geographies, reported that **48 percent of organizations admitted entering non-public company information into generative AI tools**, and that **27 percent had banned the tools at least temporarily** over privacy and security concerns. The same study found 63 percent had established limits on what data can be entered and 61 percent had limits on which tools can be used. Read those together and the picture is clear enough. Roughly half of organizations know non-public information has gone into these tools, a quarter responded with a ban, and most of the rest responded with a rule. Neither response addresses why it happened. A ban is worth being precise about: it moves the activity rather than stopping it. The work still needs doing, the tool is still one browser tab away, and the only thing that reliably changes is that people stop telling you. Source: [Cisco 2024 Data Privacy Benchmark Study](https://www.cisco.com/c/dam/en_us/about/doing_business/trust-center/docs/cisco-privacy-benchmark-study-2024.pdf) and the [accompanying release](https://newsroom.cisco.com/c/r/newsroom/en/us/a/y2024/m01/organizations-ban-use-of-generative-ai-over-data-privacy-security-cisco-study.html). ## Discovery, in rough order of effort **Expense reports.** The highest-yield and least technical source. Personal-card reimbursements for AI subscriptions tell you exactly which tools, which teams, and how long it has been going on. Start here. **SSO and OAuth grants.** Any tool someone authorised against a corporate identity is visible in your identity provider's application list, including ones nobody approved. Review it; the list is usually longer than expected. **Network and DNS telemetry.** Traffic to known AI provider domains from corporate devices. Blunt and only covers managed devices on managed networks, but it establishes scale. **Browser extension inventory.** Frequently the least governed software in the estate, often with permission to read every page the user opens. **Asking.** An amnesty produces better data than any of the above, and only works once, so spend it well. Make it explicitly non-punitive, ask what they were trying to do, and publish what you build in response. ## The response that works Discovery is the easy half. What you do next determines whether it recurs. 1. **Find out what they were trying to do.** Every shadow tool is a task the sanctioned path did not cover. That list is your roadmap. 2. **Ship a sanctioned path for the common cases**, quickly, even if it is worse than the tool they found. It has to be close enough that the difference is not worth the risk. 3. **Migrate the accounts** rather than deleting them, and take the data with you. Deleting an account someone depends on without a replacement teaches them to hide the next one. 4. **Then close the unsanctioned path**, once the alternative is real. Reversing steps two and four is the common mistake, and it is why the second wave of shadow AI is always harder to find than the first. ## Personal accounts are the durable risk A tool bought on a corporate card is at least an asset. A tool on a personal account is not: your organization's data sits in an account you do not control, held by a person who may leave, under terms nobody read, with a password you cannot rotate and no way to export. When that person leaves, the data leaves with them, and there is no offboarding step that touches it. That is the risk worth prioritising, ahead of the tool choice itself. {{< aside title="How shadow IT thinks about this" >}} The shadow IT literature settled this argument years ago: shadow adoption is a signal about unmet demand, and organizations that treated it purely as a compliance failure got the same outcome repeatedly. What changed with AI is speed and surface area. The tools are free, need no installation, and the data goes in as text rather than as a file, so none of the controls built around file movement see it. {{< /aside >}} {{< checklist >}} - Pull the last six months of expense reports for AI tool subscriptions. What is on the list? - Which third-party applications have OAuth grants against your identity provider? - What does someone in your organization do today when they need an AI capability you do not provide? - If a person who set up a personal AI account left tomorrow, what would happen to the data in it? - Have you asked, without consequences attached? - For each shadow tool you find, what is the sanctioned equivalent, and how long until it exists? {{< /checklist >}} ================================================================ # Cost URL: https://brocs.fyi/secure/cost/ Summary: FinOps for AI: who spends what on which model, and why monthly reporting is too slow to be a control. AI spend behaves differently from the spend your finance processes were built for. It is elastic, it can move an order of magnitude on a prompt change, and agents spend money in a loop. ## Why the invoice is too late A monthly invoice tells you what happened four weeks ago, in aggregate, by provider. That is enough to be alarmed and not enough to act, and by the time it arrives the loop has been running for a month. The specific mechanisms that produce surprises: **Retry loops.** An agent that fails and retries without a bound will spend continuously. This is the single most common cause of a shocking invoice. **Context growth.** A prompt that accumulates history gets more expensive with every turn, and the cost curve is quadratic in a conversation rather than linear. **A model change.** Moving to a larger model for quality reasons is a defensible decision. Making it without knowing the multiplier is not. **Cache invalidation.** If you rely on prompt caching, a small change to a prefix can silently multiply cost while everything looks identical. **Batch jobs discovering more data.** A nightly job over a growing corpus grows with it, and nobody is watching the corpus. All five are visible within hours in a spend-rate metric and invisible until the invoice without one. See [metrics](/observe/metrics/). ## Attribution first, allocation second You cannot control what you cannot attribute. The prerequisite is that every inference call carries an application, a team, and a user, which is the argument for a [gateway](/build/keys-and-models/) restated in financial terms. With attribution you can do the two things that matter: **Showback.** Tell each team what they spent. This alone changes behaviour more than most policies, because most overspend is accidental and the person causing it would fix it if they knew. **Chargeback.** Move the money. Worth doing when spend is material enough that teams should be trading it off against other budget, and premature before that. ## Quotas beat approvals, again A per-team monthly spend ceiling with alerting at 50, 80, and 100 percent gives teams freedom inside a bound and gives you a conversation at the edge instead of a surprise. Two refinements. Set a rate limit as well as a total, because a total does not stop a loop from consuming the month's budget in an afternoon. And make the ceiling raisable in minutes, or teams will hoard headroom by over-requesting. ## Cost is a design parameter Once cost is visible per request, it becomes something engineers can optimise, and the usual wins are large and unglamorous: - **Right-size the model.** A great deal of production traffic is classification and extraction that a smaller model does correctly. - **Cache aggressively.** Both prompt caching and plain result caching for repeated questions. - **Bound the loop.** A maximum tool-call count per session is a budget control and usually also a quality control, since an agent on its fifteenth attempt is not about to succeed. - **Trim context.** Most long prompts contain material that stopped being relevant several turns ago. {{< aside title="How FinOps thinks about this" >}} The FinOps discipline is built on three phases: inform, optimise, operate. AI programs usually attempt to operate without informing, which produces blunt controls like a global spend cap that stops useful work along with wasteful work. Inform first. Attribution is the whole foundation, and it is cheap to add at the start and expensive to retrofit across a mature estate. {{< /aside >}} {{< checklist >}} - What did AI cost last month, by team? If the answer is one number by provider, that is the finding. - Do you have a spend-rate alert, or only a total? - What bounds an agent's retries and tool calls? - Which team is your largest spender, and do they know? - What percentage of your traffic goes to your most expensive model, and does it need to? - If spend tripled tonight, how long until someone noticed? {{< /checklist >}} ================================================================ # Data access URL: https://brocs.fyi/build/data-access/ Summary: Connecting builders to the data they need without handing out production credentials. Masking, scoping, approvals, and the retrieval plumbing problem. Data access is where most AI projects actually stall. Not the model, not the framework: getting the right person or the right agent to the right data, with a boundary that survives review. ## Two different problems that get confused **Builder access** is a human question. An analyst needs to look at claims data to build something useful. That is a normal data governance problem with a normal answer: role, scope, purpose, approval, audit. Nothing about AI changes it except the volume of requests. **Runtime access** is a machine question. The thing you built needs to read data while it runs, on behalf of whoever is using it. That one is different, and it is where the mistakes happen. The classic error is solving the second by copying the first: give the application a service account with broad read access, and let the prompt decide what to show. That works right up until the model is asked politely for something else, or reads a document containing instructions written by someone who is not your user. The property you want is that **the data boundary is enforced outside the model**. The application asks for data as the user, the data layer applies the user's permissions, and the model only ever sees what that user could have seen anyway. Then a prompt injection gets you a rude answer rather than a breach. ## Masking, scoping, and synthetic data Not every use needs real data. Ranked by preference: 1. **Synthetic or generated data** for anything where the shape matters more than the contents. Most development and demos. 2. **Masked or tokenized production data** where realistic distributions matter. Mask at the source, not in the application, or you will find the unmasked copy in a log. 3. **Scoped real data**, narrowed to the rows and columns the job needs, time-limited. 4. **Full production access**, by exception, with an approval and an expiry. The organizations that move fastest are usually the ones with a decent answer at level one and two, because most requests never have to climb to three. ## The retrieval plumbing problem Retrieval augmented generation is presented as a model technique. In practice it is a data engineering job with a model at the end, and the hard parts are the familiar ones: **Freshness.** Your index is a copy. Copies go stale, and a confidently wrong answer from last quarter's policy document is worse than no answer. **Permissions.** If the index is built once with broad credentials and queried by everyone, you have built a system that launders access control. Permissions have to be carried into the index and applied at query time, or the index has to be partitioned by audience. **Provenance.** When the answer is wrong, you need to know which document produced it. Without a citation trail, debugging is guesswork and correcting the source has no verifiable effect. **Deletion.** When a record is deleted from the source, it has to leave the index too. This one is a legal requirement in several jurisdictions and it is routinely missed because the index is treated as a cache rather than as a copy of personal data. {{< aside title="How data governance thinks about this" >}} A data governance practitioner will recognise every item above and will point out, correctly, that the discipline already has answers: classification, purpose limitation, lineage, retention. The amendment is that retrieval indexes and prompt logs are new copies of governed data, created by application teams, often outside the catalogue. If your data map does not include the vector store and the prompt log, the map is wrong. {{< /aside >}} ## Prompt logs are a data store Every prompt and completion your organization sends is a record, and by default those records are retained by someone. They frequently contain exactly the data the rest of this page is about, pasted in by a person trying to get an answer. Treat the prompt log as what it is: a data store with a classification, a retention period, an owner, and an access control list. Then decide deliberately whether it lives with your provider, in your account, or nowhere. {{< checklist >}} - When an AI application reads data, whose permissions apply: the user's, or a service account's? - Is there a supported way to get realistic non-production data, and how long does it take? - Are permissions applied at query time against your retrieval index, or baked in at index time? - When a record is deleted from the source system, what removes it from the index? - Where do prompts and completions land, who can read them, and how long are they kept? - Is the vector store in the data catalogue? {{< /checklist >}} ================================================================ # Provisioning URL: https://brocs.fyi/run/provisioning/ Summary: Self-service infrastructure for AI work: provision, build, and deploy as one motion rather than three queues. Provisioning is the act of creating what a workload needs to exist: compute, database, storage, secrets, ingress, identity, telemetry. The Run question is whether that is one motion or a sequence of requests to different teams. ## The queue is the cost An engineer wants to ship an internal tool. They need a place to run it, a database, a secret, and a hostname. In a lot of organizations that is four requests to three teams, each with its own form and its own idea of what constitutes a complete request. The interesting cost is not the aggregate wait. It is that the wait is long enough for people to plan around it. Once a two-week provisioning lead time is common knowledge, teams start batching, over-requesting so they do not have to come back, and building workarounds on infrastructure they already have. Every one of those behaviours makes the estate harder to reason about, and none of them appear in a metric. ## Provision, build, deploy as one motion The target state is a single action that produces a running application with everything attached. Not because typing one command is intrinsically better, but because it collapses the decisions into one place where they can be made well once. What that means concretely: - **The template owns the defaults.** Backup policy, encryption, network placement, log retention, and tags are properties of the template, not of the requester's memory. - **Identity comes with it.** The workload gets its own identity at creation, so secrets and data access can be scoped to it rather than to a shared account. - **Teardown is symmetric.** Anything creatable by self-service must be destroyable by self-service, including everything it created. Orphaned infrastructure is the tax on systems that only know how to say yes. - **The record is in version control.** What exists should be reconstructable from a repository rather than from a console. ## Ephemeral by default AI work produces an unusual number of short-lived environments: an experiment, a demo, a per-branch preview, a sandbox for one agent session. If those are expensive to create, people keep them, and a kept environment becomes permanent, undocumented infrastructure holding a copy of production data. Making environments cheap to create and automatic to expire is the single most effective control on estate sprawl. An environment with a deletion timestamp at creation solves a problem that quarterly cleanup projects never will. {{< aside title="How platform engineering thinks about this" >}} The framing platform teams use is the platform as a product with users who can leave. The internal alternative to your provisioning path is a corporate card, and that competitor ships instantly with no review. If your path loses on speed, it loses entirely, and the workloads you were meant to govern end up somewhere you cannot see. {{< /aside >}} ## Quotas beat approvals For most requests, an approval step is a slow way of saying yes. A quota is the same control expressed as a budget: teams operate freely inside it, and the conversation only happens when they want more. Quotas also produce a useful signal. A team that consistently hits its ceiling is telling you something about demand, in a way that a queue of approved tickets never does. Reserve real approvals for the small set of actions that genuinely warrant one: production data access, public exposure, and spend above a threshold. {{< checklist >}} - How many separate requests does it take to get a running AI app with a database, a secret, and a URL? - Can a team destroy everything they created with one action, including the storage? - What expires an environment nobody is using? - Are backup, encryption, and retention properties of the template, or of the requester? - How many AI workloads are running on infrastructure that was provisioned by hand? - Where is the list of what exists, and is it generated or maintained? {{< /checklist >}} ================================================================ # Storage and backups URL: https://brocs.fyi/control/storage-and-backups/ Summary: Retention, lifecycle, and restore drills for AI data, including the stores nobody put in the catalogue. [Run](/run/data-and-state/) covers provisioning the stores. Control covers what happens to what is in them: how long it lives, who can reach it, whether you can get it back, and whether you can prove any of that. ## Retention has to be a decision The default retention for most AI data is forever, because nobody chose. Conversation history accumulates, prompt logs accumulate, traces accumulate, and every one of them is a copy of whatever people put in. Set a period per store, based on what it contains rather than what it is called: - **Conversation history.** Often the only record of what your system told a user, which makes it evidence. Long enough for disputes and support, short enough to bound exposure. Somewhere between 30 and 90 days is a common landing spot for internal tools. - **Prompt and completion logs.** Assume they contain personal data and credentials regardless of policy. Short by default, longer only where an obligation requires it. - **Traces.** Sample the routine, keep the abnormal. See [traces](/observe/traces/). - **Vector indexes.** No natural expiry, which is exactly why deletion has to propagate. - **Generated artifacts.** Frequently forgotten, frequently in an over-permissive bucket. The retention period is not a documentation exercise. Something has to enforce it, and that something has to be verified, because a lifecycle policy that was never applied looks identical to one that was. ## Deletion has to propagate When a person exercises a deletion right, or a document is withdrawn, it has to leave the primary store, the object storage, the index, the conversation history, the prompt log, the trace store, and any backup retained long enough to matter. Write down the propagation path once, as a list of systems and mechanisms. Most organizations discover during that exercise that two or three of the copies have no deletion mechanism at all, which is much better discovered on a Tuesday than during a regulator's clock. ## Backups are a claim until you restore one The failure is rarely that backups do not run. It is that nobody has proven a restore produces a working system. For AI workloads, add two specific checks to the drill. Restoring the primary database without the vector index leaves a system that answers from nothing, so the drill has to cover both and the ordering between them. And if the index is treated as rebuildable rather than backed up, time the rebuild. Eleven hours and a large embedding bill is a fact worth knowing before the outage. Put the drill in the calendar with a name attached, and record how long it took. The number is your actual recovery time objective, whatever the document says. {{< aside title="How records management thinks about this" >}} A records manager will ask what the retention obligation is, where the authoritative copy lives, and how disposition is evidenced. Those are the right questions and AI stacks answer them poorly, because prompt logs and traces were built as telemetry by people who did not think of themselves as creating records. The reframe is simple: if it contains personal data or documents a business decision, it is a record and the existing schedule applies. {{< /aside >}} ## Access control on the telemetry The trace store is often the least protected system holding the most sensitive material, because it was built by the platform team for debugging and read access was granted generously. Apply the same standard you apply to the source data. If only four people can read the claims table, then only four people should be able to read traces containing claims data. {{< checklist >}} - What is the retention period for conversation history, and what enforces it? - List every store that holds a copy of a customer document. Which have a deletion path? - When did you last restore an AI application from backup, end to end, as a drill? - How long does a full vector index rebuild take, and what does it cost? - Who can read the trace store today? Compare that to who can read the source data. - Is there a bucket of generated artifacts with public or broad access? {{< /checklist >}} ================================================================ # What matters URL: https://brocs.fyi/observe/what-matters/ Summary: Which signals predict incidents and which are dashboard decoration, and how to expose observability to people who are not on the platform team. Most AI observability effort goes into building a dashboard that looks impressive in a review and is never opened during an incident. This page is about the difference. ## Decoration and signal A metric is decoration if you cannot name a decision it would change. Token counts by model, on a large chart, are decoration in most organizations. Nobody looks at that chart and does something differently. Cost per session for the three applications that account for 80 percent of spend is a signal, because there is an obvious action attached. Run the test on your existing dashboard, honestly. For each panel: what decision does this change, and who makes it? Panels that survive are your dashboard. The rest can go in a query you run when you need it. ## The four questions worth instrumenting for Most useful AI observability answers one of these: 1. **Is it working for users right now?** Task success rate, error rate, time-to-first-token. The ones that belong in an objective. 2. **Is it getting worse?** Eval scores over time, refusal rate, tool calls per task, user-reported quality. Trend rather than threshold. 3. **What did it do?** [Traces](/observe/traces/). Asked after the fact, usually by someone with a deadline. 4. **What is it costing, and who is causing it?** Attributed cost. Asked monthly by finance and continuously by anyone with a budget. If a signal does not serve one of those four, it is context. Keep it, do not chart it. ## Leading and lagging Error rate is lagging: by the time it moves, users are affected. The useful work is finding indicators that move first. In practice the reliable leading indicators are: - **Tool calls per completed task**, rising. The agent is working harder for the same result, which usually means retrieval quality or instruction quality has degraded. - **Retry rate**, rising. Something downstream is flaky, or output validation is failing more often. - **Prompt length**, growing. Context accumulation, usually from a change nobody flagged, and it moves cost and latency together. - **Eval score on the pinned suite**, falling. The most direct one, and the only one that needs deliberate investment. ## Expose it beyond the platform team The people who most need AI observability are frequently the least likely to have access to it: the analyst who built the tool, the product manager who owns the workflow, the compliance officer who has to sign something. Three surfaces, and they are not the same surface: **The builder view.** My application: cost, errors, recent traces, eval results. Scoped to what I built, no query language required. **The owner view.** This workflow: task success rate, volume, cost trend, user-reported problems. Aimed at someone who cares whether it works, not how. **The evidence view.** Given a date range and a system, produce the record: what ran, what it touched, which approvals applied. Aimed at audit, and covered in [Secure](/secure/compliance/). Building only the first is the common failure. It leaves the people who decide whether to keep funding the thing with no way to see whether it works. {{< aside title="How control theory thinks about this" >}} A control loop needs a measurement, a setpoint, and an actuator. Most AI monitoring supplies a measurement and nothing else: no defined target, and no mechanism to adjust anything without a deploy. That is not a loop, it is a thermometer. When you add a metric, name the setpoint and the actuator at the same time. If either is missing, you are building decoration, however good the chart looks. {{< /aside >}} {{< checklist >}} - For each panel on your main AI dashboard: what decision does it change, and whose? - Which of your metrics is leading rather than lagging? - Can the person who built an application see its cost and traces themselves? - Is there a view aimed at someone who is not technical and owns the outcome? - When was your dashboard last opened during an actual incident? - What is the setpoint for your most-watched metric? {{< /checklist >}} ================================================================ # Why five URL: https://brocs.fyi/resources/why-five/ Summary: Why Build, Run, Observe, Control, Secure, and no other set. What was considered and rejected. Frameworks earn their keep by being the right size. Three parts and you are hiding the hard bits inside one of them. Nine parts and nobody remembers it, which means nobody uses it in the meeting where it would have helped. Five is not a design choice made for symmetry. It is where the sentence came out. ## The sentence The framework started as a question from an engineering leader at a healthtech company, after several weeks of evaluating the AI tooling market: > I need somewhere to build it, somewhere to run it, a way to see what it's doing, and > ensure it doesn't go off the rails. That is Build, Run, Observe, Control, in order, from someone who had no framework and no interest in one. He was describing the shape of the hole. Secure is the fifth because the next conversation is always with the CISO, the compliance officer, or the regulated buyer, and it is not a subset of the other four. "It doesn't go off the rails" is an operational statement about your own system. "Prove it, to an auditor, for a system that generates its own text" is a different job with different artifacts and a different owner. ## The test each letter has to pass A letter earns its place if all four of these hold. 1. **Someone owns it, and it is not the same someone.** Build belongs to platform or developer experience. Run belongs to infrastructure. Observe belongs to whoever carries the pager. Control belongs to architecture and identity. Secure belongs to security, compliance, and finance. Five letters, five different budget lines and five different rooms. 2. **Skipping it produces a distinct, observable failure.** Not a worse version of another letter's failure. The [failure-mode library](/resources/failure-modes/) is the evidence for this one. 3. **It has a mature adjacent discipline to borrow from.** None of these are new. Each letter has decades of prior art that transfers with modest amendment. See [adjacent practices](/resources/adjacent-practices/). 4. **You can be at zero on it while being strong elsewhere.** If a letter always moves with another letter, it is not a letter, it is a facet. ## What was considered and rejected **Govern as a separate letter.** Governance without enforcement is a document. The useful version of governance is policy encoded in the place where the action happens, which lands inside Secure and Control rather than floating above them. A sixth letter here would have created a home for exactly the artifact the framework is arguing against. **Data as a separate letter.** Tempting, because data is where most AI programs actually stall. It failed test one: data access for builders is a Build problem, data at rest and in motion is a Run problem, data retention is a Control problem, and data residency is a Secure problem. Pulling it out creates a letter that nobody can own end to end and leaves four letters with holes where the data used to be. **Cost as a separate letter.** Inference cost is genuinely different from compute cost: more elastic, harder to forecast, and easy to hide in a single corporate card. But cost control without attribution is impossible, attribution requires per-app and per-team telemetry, and that telemetry is Observe. The decision to cut off a team is Secure. The letter would have been a reporting layer over two other letters. **Evaluate, or Measure, as a separate letter.** Evals are how you know Observe is telling you something true. They belong to Observe the way tests belong to Build. **Merging Control into Run.** This is the most common objection, usually from people with a strong platform team, and it is wrong for a specific reason: Run answers "is it up", Control answers "can I change it, and can I change it back". Plenty of organizations have an excellent Run story and no ability to move a workload between model providers without a code change. That is a real gap and it needs a name. ## Why the order The letters are in the order work happens. Someone builds something, it runs, you watch it, you steer it, you answer for it. That order is also the order things get skipped: almost every organization starts at Build, most get to Run, fewer reach Observe, and Secure is usually a retrofit after an incident or an audit. The order is not a maturity model. You do not finish Build and move on. Each letter hands off to the next and the last hands back to the first: what you learn in Secure changes what you are willing to let people Build. ================================================================ # Adjacent practices URL: https://brocs.fyi/resources/adjacent-practices/ Summary: How BROCS sits with DevOps, SRE, SecOps, platform engineering, and the compliance frameworks you already answer to. BROCS is not a replacement for anything. Every letter has a mature discipline behind it that has already solved most of the problem for non-AI systems. The value of the framework is in naming which parts transfer unchanged, which parts need amendment, and which parts are genuinely new. If you have a strong platform practice, you are further along than you think. If you have none, do not start with AI; start with the adjacent discipline. ## DevOps and DORA (Build) **Transfers unchanged.** Lead time for changes is the single most useful metric to carry across. The question "how long from someone having an idea to that idea running somewhere real" works exactly as well for an AI app as for a service, and the answer is usually worse. **Needs amendment.** The DORA population is engineers. The Build surface includes people who are not engineers and will never open a terminal, and a golden path they cannot walk is not a golden path. Measure lead time for the analyst as well as for the platform engineer. **Genuinely new.** The artifact under change control is now partly English. A prompt is executable, and the review process that reads a code diff carefully will skim a prompt diff. The [Amazon Q wiper incident](/resources/failure-modes/#amazon-q-wiper) is that gap, shipped to a million installs. ## SRE (Run and Observe) **Transfers unchanged.** Error budgets, golden signals, blameless postmortems, and the principle that reliability is a feature you spend on deliberately. Also the discipline of testing restores rather than trusting backups. **Needs amendment.** The golden signals need company: tokens, cost per request, tool calls, and refusal or failure rate. Saturation means something different when the constrained resource is a provider rate limit you do not control. **Genuinely new.** Correctness is a spectrum and it moves on its own. A service that returns 200 with a subtly worse answer than last week is a new failure mode. It looks like nothing on a traditional dashboard, and the first report usually comes from a customer. That is why evals belong next to monitors. ## SecOps and the OWASP LLM Top 10 (Secure) **Transfers unchanged.** Least privilege, defence in depth, credential rotation, and the habit of asking what a component can reach before asking whether it is trusted. **Needs amendment.** The perimeter model assumed data moved when a human moved it. An agent with tool access and standing permissions moves data continuously as a side effect of doing its job, so the interesting boundary is no longer the network edge, it is the set of things one component can touch. **Genuinely new.** Indirect prompt injection has no clean analogue. Untrusted content is now an instruction channel, which means every document, ticket, web page, and email an assistant reads is a potential input to its control flow. The [EchoLeak vulnerability](/resources/failure-modes/#echoleak) is the reference case: no click, no attachment, just an email the assistant read. ## Platform engineering (Build and Run) **Transfers unchanged.** Internal platform as a product, paved roads, self-service provisioning, and the observation that the compliant path has to be the fast path or it will lose. **Needs amendment.** The tool layer changes faster than platform teams are used to building for. A platform that hard-codes today's agent CLI will be a migration project within a year. Build the substrate, not the integration. **Genuinely new.** Very little. This is the discipline BROCS borrows from most heavily and amends least. ## Control theory (Observe and Control) Observe and Control are one loop, and naming them as two letters is deliberate. A system you can measure but not adjust is a dashboard. A system you can adjust but not measure is a guess. Most AI programs build the dashboard first and then discover that the only available adjustment is to turn the whole thing off. ## GRC, NIST AI RMF, and the EU AI Act (Secure) BROCS is an engineering framework, not a compliance framework, and it does not compete with either. The relationship is mechanical: compliance frameworks tell you which outcomes you must be able to evidence, and BROCS is about whether your platform can produce that evidence as a byproduct of running rather than as a quarterly project. The NIST AI Risk Management Framework organises around Govern, Map, Measure, and Manage. Map and Measure land on Observe. Manage lands on Control. Govern lands on Secure. If you are already running the RMF, BROCS is the question of where each function is actually implemented in your stack. The EU AI Act works the same way from the other direction: obligations attach to outcomes, and the practical question is whether your system can produce records of what it did without a person reconstructing them. That is the [agent trace](/resources/glossary/#agent-trace), which is an Observe capability with a Secure requirement attached. ## FinOps (Secure) **Transfers unchanged.** Visibility, attribution, showback and chargeback, and the cultural point that the team causing the spend has to see the number. **Needs amendment.** Inference spend is more elastic than compute spend and can move an order of magnitude on a prompt change, so monthly reporting is too slow to be a control. **Genuinely new.** Agents spend money in a loop. A retry policy is now a budget decision. ================================================================ # Compliance URL: https://brocs.fyi/secure/compliance/ Summary: HIPAA, SOC 2, PCI, FedRAMP, and the EU AI Act: audit evidence as a platform output rather than a quarterly scramble. Compliance is where the rest of the surface gets examined by somebody who was not in the room when it was built. The BROCS position is narrow and practical: your platform should produce audit evidence as a byproduct of running, rather than as a project that starts when an auditor sends a request list. ## The scramble, and why it recurs The pattern is familiar. An audit is scheduled. Someone assembles a list of AI systems by asking around. For each one, engineers reconstruct who had access, what data it touched, and which approvals applied, from logs that were not designed for the question. It takes weeks, the evidence is partial, and the same exercise repeats next year because nothing changed except that everyone is more tired. The scramble is not caused by weak controls. It is caused by controls whose operation is not observable. A control that runs and leaves no record is indistinguishable, to an auditor, from one that does not run. ## What evidence actually gets asked for Across most frameworks the requests reduce to a small set: - **An inventory.** Which AI systems exist, what they do, what data they process, who owns them. This is the request that most often cannot be answered, and it is a [Build](/build/idea-to-production/) and [Control](/control/) problem, not a compliance one. - **Access records.** Who could reach the system and its data during the period, and who actually did. From [ingress](/control/ingress/) and [identity](/control/identity/). - **Change records.** What changed, when, who approved it. From [configuration](/control/configuration/). - **Processing records.** What the system did on behalf of whom. From [traces](/observe/traces/). - **Retention and disposal.** What is kept, for how long, and proof that deletion happened. From [storage](/control/storage-and-backups/). - **Third-party posture.** Which providers process your data, under what terms. Every one of those is produced by a letter of the surface. If the letters are covered, the audit is a query. If they are not, the audit is archaeology. ## The frameworks, briefly and without pretending to be legal advice **SOC 2** is about whether your stated controls operate. AI systems are in scope when they touch systems in scope, which is more often than teams assume. The recurring finding is the inventory: AI tools adopted outside the normal path do not appear in the system description. **HIPAA** turns on whether protected health information reaches the model. If it does, the endpoint needs to be covered by a Business Associate Agreement, and whether a given endpoint is covered has to be enforced by [routing](/control/routing/) rather than documented in a policy. **PCI DSS** is mostly about keeping cardholder data out of the AI path entirely. The practical control is redaction at the gateway plus scoping so the data is not reachable. **FedRAMP** and equivalents constrain where processing happens, which makes [portability](/run/portability/) a gating requirement rather than a preference. **The EU AI Act** attaches obligations to outcomes and risk categories. The operational consequence for most engineering teams is record-keeping: being able to show what a system did, on what basis, without a person reconstructing it. That is the [agent trace](/observe/traces/) with a retention policy attached. **The NIST AI Risk Management Framework** is voluntary and organizes around Govern, Map, Measure, and Manage. It maps onto the surface cleanly: Map and Measure are [Observe](/observe/), Manage is [Control](/control/), Govern is Secure. If you are already running the RMF, BROCS is the question of where each function is implemented in your stack. ## Continuous evidence The target is that any of the requests above can be answered by running a query over a date range, without asking an engineer to remember anything. Getting there is mostly about deciding, once, that the record is a deliverable of the platform rather than a side effect of logging. Practically: - The inventory is generated from what is deployed, not maintained by hand. - Access records come from one ingress rather than five. - Change records come from version control, because configuration lives there. - Processing records come from traces with retention set by what they contain. - Deletion is evidenced, not asserted. That work is not free. It is considerably cheaper than the annual scramble, and unlike the scramble it also makes incidents shorter. {{< aside title="How auditors think about this" >}} An auditor tests design and operation separately: is the control capable of addressing the risk, and did it actually run during the period. The second question is where AI programs fail, because the evidence was never emitted. Framing every control as a testable assertion with a continuously produced artifact answers both at once, and it converts an audit from an interrogation into a data pull. {{< /aside >}} {{< checklist >}} - Can you produce a current inventory of AI systems, generated rather than maintained? - For a date range last quarter, can you show who accessed an AI application? - Can you show what changed in a prompt, when, and who approved it? - Where PHI or cardholder data is involved, what enforces the endpoint restriction? - Can you evidence deletion, or only assert it? - How many person-weeks did your last audit cost, and which of the questions above caused most of it? {{< /checklist >}} ================================================================ # Idea to production URL: https://brocs.fyi/build/idea-to-production/ Summary: Golden paths, templates, and scaffolds. DORA lead time applied to AI work, and what it takes for non-engineers to build like engineers. The last part of Build is the path itself: what a person actually does between having an idea and having something running that other people use. If that path is undocumented, every project rediscovers it, and most give up somewhere in the middle. ## Make the compliant path the fast path This is the whole of platform engineering compressed into one sentence, and it is the only governance strategy that survives contact with people under deadline. If the approved way to ship an AI application involves a design review, a security questionnaire, a ticket for a database, a ticket for a secret, and a ticket for a hostname, then the unapproved way, which is a personal cloud account and a share link, will win. Not because anyone is reckless, but because it works today and the other one works in three weeks. A golden path is the same set of controls delivered as a template instead of a queue. The review happened once, when the template was built. Using the template is how you inherit it. ## What a golden path actually contains A usable scaffold for AI work covers, at minimum: - **A runtime** it deploys to, with the environment already wired. See [Run](/run/runtime/). - **Model access** through the gateway, with no key in the repository. See [keys and models](/build/keys-and-models/). - **Data access** as the calling user, not as a service account. See [data access](/build/data-access/). - **Telemetry on by default**: traces, cost attribution, and errors, without the builder configuring anything. See [Observe](/observe/). - **Ingress and SSO** so the thing has a URL and only the right people can open it. See [Control](/control/ingress/). - **An eval harness**, even a trivial one, so there is somewhere to put the first test case when quality becomes a question. The list is unremarkable. The point is that it is one command rather than six tickets, and that the person shipping did not have to know any of it existed. ## Lead time, measured honestly Borrow the DORA metric directly and apply it to AI work: how long from a stated idea to something running that a real user can reach. Measure the whole thing, including the waiting, because the waiting is the finding. Two refinements make it more useful: **Measure by population.** The engineer's lead time and the analyst's lead time are different numbers, and the second one is usually the one nobody has looked at. **Measure the second change, not just the first.** Getting something into production once is a project. Changing it on Thursday because a user complained on Wednesday is a platform. If the second number is much worse than the first, you have a demo pipeline rather than a production path. {{< aside title="How DORA thinks about this" >}} The DevOps Research and Assessment program's finding, repeated across years of data, is that lead time, deployment frequency, change failure rate, and time to restore move together, and that they are properties of the system rather than of the people in it. Applied here: if AI projects are slow at your organization, the productive question is which stage of the path is queueing, not which team is underperforming. {{< /aside >}} ## Non-engineers building real things The interesting growth in AI usage is not engineers writing code faster. It is people who were never going to write code producing working tools for their own team. That is genuinely valuable and it is also where governance usually breaks, because the tools those people reach for are the ones with no organizational boundary at all. The answer is not to stop them. It is to provide a path with the same guardrails and a much lower floor: - A builder surface they can actually use, where the hard parts are already decided. - The same identity, data scoping, and telemetry as the engineering path, inherited from the template rather than configured. - A clear line between "useful for my team" and "load-bearing for the company", with a real process for crossing it. Something that starts as a personal tool and quietly becomes a dependency is a known way to acquire an outage. ## Production means someone owns it The last checkpoint is ownership. A running application with no named owner is an incident waiting for a trigger, and AI applications acquire this status faster than most, because the person who built it in an afternoon did not think of it as a system. Ownership means a name, an escalation path, and alerts that reach that person. That is an [Observe](/observe/alerts/) capability, and it is the difference between a pilot and production. {{< failure id="replit-prod-db" >}} {{< checklist >}} - What is the actual command or click that starts a new AI application here? Can you demonstrate it in this meeting? - How long from idea to a URL a colleague can open, for an engineer and for an analyst? - What does the template give you for free: runtime, keys, data, telemetry, ingress, evals? Which are missing? - How many AI applications are running right now with no named owner? - When something built by a non-engineer becomes load-bearing, what process notices? - Is development separated from production by more than a naming convention? {{< /checklist >}} ================================================================ # Model behaviour URL: https://brocs.fyi/observe/model-behavior/ Summary: Drift, silent provider updates, and quality regressions: the failures that return a 200 and look like nothing on a dashboard. Every other page in [Observe](/observe/) is about a system failing in ways your existing monitoring understands. This one is about the failure that returns 200, completes in normal time, and gives a worse answer than it did last week. ## Four ways behaviour changes without you changing anything **The provider updated the model.** You called the same name and got a different model. Behaviour shifts, sometimes better, sometimes worse for your specific prompts, and the only notice was a changelog entry. **The retrieval corpus changed.** Someone updated the source documents, or the index rebuilt with a different chunking strategy, and the model is now answering from different material. **The prompt changed upstream of you.** A shared system prompt, a policy header, or a tool description was edited by another team. Your application inherited it. **The input distribution changed.** Nothing in your system moved. Users started asking different questions, or the same questions differently, and the system was never good at those. Only the fourth is visible without deliberate measurement, and only sometimes. ## Evals are the answer, and they are unglamorous An eval is a fixed set of inputs with a way of judging output. Run it on a schedule and on every change. That is the whole idea. What makes an eval suite useful: **It contains your actual failures.** The highest-value cases are the ones that went wrong in production. Every incident should end with a case added. **It is versioned with the thing it tests.** A suite that drifts alongside the prompt cannot detect regression, because both moved. **It is small enough to run constantly.** Fifty good cases you run on every change beat a thousand you run quarterly. **It scores something specific.** "Is this good" is not a scoring function. Did it cite the right document, did it produce valid JSON, did it refuse when it should have, did it avoid the phrase legal asked about. **It has a pinned control.** Run the same suite against a pinned model version alongside the floating one. When they diverge, you know it was the provider rather than you. ## Pin, then move deliberately If your application names a model without a version, the provider decides when your behaviour changes. Pin the version. Take the update as a change: run the eval suite against the new version, compare, then move. That converts a surprise into a scheduled task, and it makes the question "did anything change" answerable. The counterargument is that pinning means missing improvements and eventually hitting a deprecation. Both are true, and both are manageable, which is more than can be said for discovering a behaviour change through a customer complaint. See [pinning](/control/routing/). ## The canary that costs almost nothing Send a small set of known inputs through the production path on a schedule, several times an hour, and compare against expected properties. Not to grade quality precisely, just to notice a step change. It is cheap, it catches provider incidents and configuration mistakes long before users report them, and it works even when real traffic is too low or too varied to trend. {{< failure id="air-canada-chatbot" >}} {{< aside title="How machine learning operations thinks about this" >}} The MLOps discipline has been dealing with drift for years and arrived at monitoring input distributions and output distributions separately, because they fail differently. The amendment for generative systems is that the model itself is now a moving dependency you do not control, which is closer to a third-party API than to a model you trained. Version pinning and contract testing are the right analogies. Retraining is not. {{< /aside >}} {{< checklist >}} - Does your application specify a model version, or just a model name? - Do you have an eval suite? How many cases, and when did it last run? - Does every production incident end with a new eval case? - Would you find out about a quality regression from your own measurements or from a user? - Who else can change a prompt your application depends on? - What is your canary, and how often does it run? {{< /checklist >}} ================================================================ # Portability URL: https://brocs.fyi/run/portability/ Summary: Hybrid by default. Multi-cloud, on-premise, and edge, because the runtime has to go where the data already is. Portability is the ability to run the same workload somewhere else without rewriting it. In BROCS it is not a hedge against vendor lock-in. It is a functional requirement, because in a lot of organizations the data is not all in one place and it is not going to be. ## The runtime goes where the data is The sequence that plays out repeatedly: a company adopts an AI platform, it works, and then a business unit says the data for their use case cannot leave their environment. Sometimes that is a regulator, sometimes a customer contract, sometimes a country, and sometimes it is simply a forty-terabyte dataset that is not moving. At that point there are three options. Move the data, which is usually forbidden or impractical. Exclude the business unit, which means the platform is not the platform. Or run the same system in that environment, which requires that the system was built to be run in more than one place. The third only exists if you chose it in advance. It is not a feature you add later. ## What portability actually requires It is less about avoiding every managed service and more about where the couplings are. **Package the workload, not the environment.** Containers and declarative deployment, so placement is a configuration decision rather than a rewrite. **Abstract the model endpoint.** The application asks for a capability; something else decides which provider or local model serves it. That is [routing](/control/routing/), and it is what lets an on-premise deployment use a local model while the hosted one uses a vendor endpoint, with the same application code. **Abstract the data plane, within reason.** Object storage and SQL are portable in practice. Bet on a proprietary queue or a vendor-specific vector service and you have bought a rewrite. **Keep identity federated.** The single most painful part of a second environment is usually authentication. Federating to one identity provider from the start is cheaper than reconciling two user directories later. **Keep the control plane thin and the data plane self-sufficient.** If a workload in a customer's datacentre stops serving when your central control plane is unreachable, it is not deployed there in any meaningful sense. ## One system, everywhere, is a different claim The weak version of portability is "we could migrate if we had to". The strong version, and the one regulated enterprises actually need, is that the same platform runs in all the places at once, managed the same way, with one set of policies. The difference matters because the weak version still leaves you operating two systems during the years it takes to move. A global organization with a data residency requirement in three jurisdictions does not want a migration path. It wants one system with three placements. That has a design consequence: placement has to be a property of a workload rather than a property of an installation. If choosing a different region means standing up a parallel copy of your whole platform, you have built the weak version. {{< aside title="How hybrid cloud thinks about this" >}} The hybrid cloud lesson, learned expensively over a decade, is that the abstraction has to be at the workload level rather than the infrastructure level. Attempts to abstract whole clouds produced lowest-common-denominator platforms nobody enjoyed using. Abstracting the deployment unit and the small set of interfaces it depends on worked. Apply the same restraint here: abstract the model endpoint and the deployment unit, not the entire cloud. {{< /aside >}} ## Sovereignty is the sharp end For some organizations this is not a preference. Public sector bodies, healthcare providers, and financial institutions in several jurisdictions have legal constraints on where processing occurs and who can compel access to it. A platform that can only run in one vendor's cloud cannot serve those organizations at all, regardless of how good it is. If they are in your market, or you are one of them, portability is a gate rather than a nice-to-have, and the three sovereign paths (local models, models through your own cloud account, and contractually covered endpoints) all have to be live options rather than roadmap items. {{< checklist >}} - Could you run your primary AI workload in a different cloud next quarter? What exactly would break? - Is the model endpoint an abstraction, or does application code name a provider? - If your central control plane were unreachable for a day, would deployed workloads keep serving? - Do you have a data residency requirement today? Will you within a year? - Is placement a property of a workload, or does a new region mean a new installation? - Which proprietary services are you coupled to that have no portable equivalent? {{< /checklist >}} ================================================================ # Routing URL: https://brocs.fyi/control/routing/ Summary: Model and provider routing, pinning, and failover: how switching cost is held near zero. Routing is the decision, made at request time, about which model or provider serves a call, and whether that decision can be changed centrally. It is the mechanism that makes several other claims in the framework true. Tool churn is survivable because routing absorbs it. [Portability](/run/portability/) is possible because the same application can use a vendor endpoint in one placement and a local model in another. [Sovereignty](/resources/glossary/#sovereignty) is achievable because the routing layer knows which endpoints are contractually covered and enforces it. ## The anti-pattern Application code names a provider and a model. It reads a key from an environment variable and calls the provider SDK directly. Everything downstream inherits that decision. Changing model means a code change and a deploy, per application. Cost attribution has to be reconstructed from provider invoices. There is no single place to add a guardrail, a rate limit, or a redaction step. And when a regulated business unit says their data cannot go to that provider, the answer is a project rather than a configuration change. ## What the routing layer decides A gateway sitting between applications and providers can make several decisions consistently, and each one is painful to retrofit: **Which model.** By application, by environment, by data classification, or by the caller. The classification case is the one that matters most in regulated organizations: requests tagged as containing protected data route only to covered endpoints, and that is enforced rather than documented. **Which version.** Pinned by default. See below. **What happens on failure.** Retry with a bound, fail over to a second provider, or degrade to a smaller model. Decided once, applied everywhere, and bounded so retries cannot become a budget event. **What is allowed through.** Redaction of credential patterns, personal data handling, and whatever policy checks apply, in one place rather than in each application. **What gets recorded.** Tokens, cost, latency, model, and identity, on every call. This is where [metrics](/observe/metrics/) come from. ## Pin by default If your application requests a model by name without a version, the provider decides when your behaviour changes, and you find out from a user. Pin the version in the routing layer. Take updates as a deliberate change: run the [eval suite](/observe/model-behavior/) against the new version, compare, then move the pin. The version becomes configuration, which means it is reviewable and revertible like any other change. Keep a floating alias alongside the pinned one for a canary that runs the same suite continuously. When the two diverge, you learn about a provider change on your own schedule. ## Failover is not free Two providers with the same interface is not two providers with the same behaviour. A prompt tuned for one will perform differently on the other, sometimes much worse, and a failover that silently degrades quality is a quiet incident rather than a save. If failover matters, run the eval suite against the fallback too, and know what you are falling back to. If the fallback is meaningfully worse, say so in the response or in the interface rather than pretending nothing happened. The honest version of failover for many organizations is a smaller, cheaper, faster model that handles a subset of requests correctly, plus a clear message for the rest. That is more useful than a second frontier model nobody has tested. {{< aside title="How API gateways think about this" >}} Everything on this page is the standard API gateway argument, applied to model providers: centralize cross-cutting concerns so applications do not each implement them differently and wrongly. The reason it usually does not happen here is that calling a provider SDK directly is three lines and works immediately, so the first ten applications do it that way before anyone builds the gateway. Retrofitting is possible and it is a lot of small pull requests. {{< /aside >}} {{< checklist >}} - Could you move one application to a different model provider without a code change? - Is the model version pinned, and who decides when it moves? - Does anything enforce that classified data only reaches approved endpoints? - What is your retry policy, and what bounds it? - If your primary provider had a two-hour outage, what happens? Has that been tested? - Where is the single record of every inference call your organization makes? {{< /checklist >}}