Artificial intelligence (AI) and machine learning (ML) are two fields that work together to create computer systems capable of perception, recognition, decision-making, and translation. Separately, AI is the ability for a computer system to mimic human intelligence through math and logic, and ML builds off AI by developing methods that "learn" through experience and do not require instruction. In the AI/ML Zone, you'll find resources ranging from tutorials to use cases that will help you navigate this rapidly growing field.
Evals in CI: How to Catch Agent Regressions Before Production Does
How to Migrate From LangChainGo to Genkit Go
TL;DR: The Hidden Cost of Switching AI Models A new AI model arrives that is cheaper per token, scores better on benchmarks, and seems to require nothing more than a setting change. However, the token bill shows only part of the cost of switching AI models. There is also the effort to check whether your workflows, for example, the one to create status reports for stakeholders, still produce outputs in line with your AI Definition of Done. More often than not, this task remains unaligned with the decision to switch AI models. In the worst case, switching AI models behind a business workflow can raise operating costs despite cheaper tokens, because business cases can miss the revalidation effort. Thesis: This article explains the recurring operational cost of switching AI models behind a business workflow: why the revalidation effort may disappear from upgrade decisions, how to screen a switch, and how Agile teams use an AI Definition of Done, test evidence, and an accountable owner to stay in control. Why a Cheaper Model Can Cost You More Your vendor has announced a new model. It costs less per million tokens than the one behind your team's workflows, it beats its predecessor on every benchmark the release notes care to mention, and switching seems to require nothing more than a changed setting in a configuration file. The business case writes itself, which is exactly the problem, because it writes itself from the price list. A lower price per token is a fact about the model, whereas lower operating costs are a claim about your workflow. That claim depends on work no price list contains: somebody has to check whether the workflow still produces acceptable results after the switch, adapt whatever no longer does, and keep checking afterward. That effort recurs with every model change, and it vanishes from the decision whenever existing staff absorb it, because nobody "invoices" for their afternoons to create the desired transparency. The Upgrade That Looks Like a Configuration Change Take a hypothetical but ordinary case. A Product Manager runs a workflow that drafts the weekly stakeholder status report: its agent takes the export from the team's project tracker, the product roadmap, and customer input from a variety of sources. It builds on a skill that describes the report structure, including tone instructions, and the model produces a two-page draft that the Product Owner reviews, corrects, and sends out every Friday. (Yes, a written status report in an Agile organization; stakeholders who skip, for example, the Sprint Review still want to know what happened, and a page they read beats a meeting they avoid.) Over a few months, the review has settled into a quick pass that mostly fixes phrasing. Then the vendor releases a cheaper model, and the switch looks like a one-line change. When the Report Still Reads Well and Is Wrong After the switch, the reports still arrive on time, in the right structure, and in fluent prose. In the third week, however, the draft describes a blocked item as "on track," because the new model dropped the one sentence in the tracker comment explaining that the item waits for a decision from the legal department. The report reads smoothly; nevertheless, it would have told the stakeholders the opposite of the truth, and the Product Manager caught it only because they happened to know that particular item. If the team had written an AI Definition of Done for its status reports, with a verification level that requires checking every status claim against the project tracker, the report would have failed on the spot; without one, catching the error depended on the Product Owner's memory. (Download the complete A3 Delegation System template including the AI Definition of Done above.) This is the failure that can make switching AI models expensive: the workflow remains technically operational while it no longer produces acceptable output. A loud failure, say, a rejected parameter or a broken output format, stops the workflow with an error message, and somebody fixes it before lunch. The quiet failure passes every technical check and lands in front of the reviewer, who now reads every report with more suspicion than before, which is where the correction effort starts to climb. The same mechanism explains why a quick trial before the switch proves so little: model output can vary from one run to the next, so one successful run provides limited evidence, and the new model may well have produced a correct report on the day somebody tried it. Hence, every switch of the model behind a production workflow raises a revalidation question. By revalidation, I mean checking, before you approve the changed workflow for production use, that it still meets its agreed standard, and then inspecting its actual results after deployment. For teams that work with an AI Definition of Done, the trigger is already on paper: the standard names the model tier that suffices for each task class and carries a sign-off with a review date, so a model switch leaves that sign-off without a basis until somebody renews it. The depth of that check should depend on what a failure costs, as a brainstorming assistant and an agent that changes customer records do not deserve the same scrutiny. Where the Switching Cost Hides The explicit charges are easy to find: the new model's token price, perhaps a few more tokens per report if the new model writes longer drafts, and, in larger setups, the invoices for tooling or outside help with the migration. Additional costs include operational effort: the hours spent comparing old and new reports before the switch, the extra minutes of correction every Friday since, the test cases somebody has to maintain, the rework when a wrong report has already gone out, and whatever the Product Owner did not do in the meantime. (Have I mentioned the cost of losing stakeholder trust because of a faulty report?) Salaries are on the books, of course; however, existing staff budgets absorb this effort, and unless somebody attributes it to the migration, it stays out of the business case. Two days a team member spends validating a migration create no new cash expense, yet those two days are gone. That is what I mean by hidden: the cost is on the books, just not on the page where the decision gets made. Consuming more tokens per task can also outweigh a lower token price, more retries, higher latency, or more human correction. So the unit of comparison is the complete workflow at an acceptable quality level, not the token price list. A Screening Question Before You Switch For a switch motivated by cost savings, one division gives you a screening question: divide the one-off migration and revalidation cost by the net monthly savings to get the number of months it takes to recover the investment. "Net" is the word to watch, as it means the savings compared with the existing workflow after changes in review time, corrections, retries, and ongoing maintenance. Meeting the minimum standard, as such, is a precondition rather than a term in the formula: a cheaper workflow that sends wrong reports to stakeholders does not qualify, whatever the arithmetic says. Then ask whether the expected savings justify the investment, allowing for further migration and revalidation costs. A later change does not erase the savings you have already made. However, it brings its own revalidation cost, and vendors retire models on their own schedule: Anthropic, for example, retired Claude Sonnet 4 and Claude Opus 4 on June 15, 2026, and Claude Opus 4.1 on August 5, 2026. Treat the payback figure as a screen, not a forecast; it works when net savings are positive and reasonably stable, and it tells you whether the switch deserves a closer look. Beware, though: Upgrades motivated by quality or new capabilities need a different judgment: weigh that benefit against the additional cost directly, without squeezing every improvement into a monetary payback calculation (the attempt invites invented precision as a misleading metric). When the Vendor Decides for You Not every switch is voluntary. Anthropic commits to at least 60 days of notice before retiring a publicly released model, and on September 30, 2026, it notified developers that Claude Sonnet 4.5 is scheduled to retire on November 30, 2026. OpenAI gives generally available models at least 6 months of notice, specialized variants at least 3 months, and preview models much less, such as 2 weeks; all of these minimums yield when safety or compliance concerns call for a faster retirement, in which case OpenAI promises "as much notice as reasonably possible." A forced migration changes the question from whether switching is worthwhile to which viable alternative to choose: Moving to the successor modelChanging the providerReducing the workflow's scopeReverting temporarily to manual workRetiring the workflow altogether Teams that run an AI Delegation Audit will recognize the list, as the audit's decisions overlap with it (change the model tier, change the A3 category, update the AI Definition of Done, or retire the delegation). The audit counts retiring an automation that no longer justifies its audit cost as a successful outcome. Continuing the automation is itself a decision, and it deserves the same revalidation as a voluntary switch, with less time to do it. If the Product Manager first has to work out what an acceptable status report looks like, much of the notice period is gone before the first test runs, so the evidence has to exist before the notice arrives. Evidence That Survives the Switch The evidence consists of four things, kept together: examples of acceptable and unacceptable work, the criteria you used to judge them, the relevant workflow configuration (prompt, skills, instructions, data, and context), and the results the current workflow produces on those examples. For the status report, that might be a dozen past project tracker exports, the reports you consider correct, and a note on why the blocked-item report was wrong. If the workflow already has an A3 Handoff Canvas, its Records field has settled in advance what to keep (prompts, skills, inputs, outputs, edits, and approvals), which means the evidence accumulates while the workflow runs instead of being reconstructed under a deadline. Keep that evidence somewhere your organization controls, because testing tools are dependencies, too. OpenAI announced on June 3, 2026, that it is shutting down its Evals platform: existing evals become read-only on October 31, 2026, and the dashboard and API shut down on November 30, 2026. A team that kept its test cases only in that platform must migrate its testing setup, and if its model needs replacing at the same time, the two migrations compound the work. Passing the same cases supports the decision to deploy; however, a new model can pass every existing case and still fail in ways those cases never covered. So, retain the existing cases, add a case for every newly discovered failure (the blocked item is now case number 13), and inspect the actual results for a while after deployment. Who Approves Continued Use? Evidence that nobody acts on is an archive, so somebody has to be accountable for the check happening before a switch, for recording the decision to keep using the workflow, and for noticing when production results drift. Call that person the "workflow owner." They do not have to run every test personally, but they own the answer to "does this still work?" In the A3 Delegation System, the AI Delegation Audit inspects whether this practice works, much as a Retrospective inspects how the team works. One of its four checks, model fit, asks whether the assigned model still suits the task and its risk level. The audit does not gate individual switches, which a recurring inspection cannot do; the model change remains the trigger. One limit applies to all of this: you can only revalidate the workflows you know about, and an AI Workflow Inventory, even one that deliberately lists the shortcuts nobody approved, covers only what your discovery turns up. A workflow a team member runs privately through a personal account can change without the team knowing about it, let alone applying its agreed checks. Shadow IT always comes at a price. Conclusion: One Workflow Before Switching AI Models Pick one consequential recurring workflow, one where a wrong output would reach a stakeholder, a customer, or a decision before anybody noticed. Then do four things: Name the owner: The person who approves continued use after the next model change.Write down the standard: What counts as acceptable work for this workflow, ideally as an AI Definition of Done with the model tier it was signed off for and a review date. (If you work with Scrum, the parallel to the Definition of Done is deliberate.) If no such standard exists, writing it is your first task, and the hardest one, because without a standard there is nothing to revalidate against.Collect five starter cases: Real past inputs with outputs you consider acceptable and, if you have one, an output you consider wrong, together with the results the current workflow produces today.Record what runs it: The model and provider as your tool shows them, and where the evidence lives. (If you keep an AI Workflow Inventory, put this into a separate check record under the workflow's inventory number rather than into the inventory itself.) Five cases start the exercise; they do not validate anything on their own, and they are not supposed to. Then apply one test: if your vendor announced the retirement of that model tomorrow, could the owner demonstrate within the notice period that the workflow still meets its standard on the new one? If the honest answer is no, you have uncovered operational work that the model's price list leaves out. Key Questions This Article on Switching AI Models Answers Does a Cheaper AI Model Lower the Cost of a Business Workflow? A cheaper AI model does not necessarily lower a workflow's cost, because the token price is only one part of what the workflow costs to run. A cheaper model may need more tokens, more retries, or more human correction, and the effort to revalidate the workflow adds staff time that a business case built from token price lists may not capture. The unit of comparison is the complete workflow at an acceptable quality level. What Are the Hidden Costs of Switching AI Models? The hidden costs of switching AI models are the internal efforts that no vendor bill shows: comparing old and new outputs before the switch, extra review and correction afterward, maintaining test cases, and reworking wrong output that already went out. Existing staff budgets absorb this effort, so a business case built from token prices can miss it: two days of validation work creates no new invoice yet still consumes capacity, so it vanishes in the budget noise. How Do You Check Whether a Workflow Still Works After an AI Model Change? Revalidate the workflow: before approving it for production use, check it against an agreed standard, such as an AI Definition of Done, and a set of saved cases, then inspect its real results after deployment. Keep acceptable and unacceptable examples, judging criteria, workflow configuration, and previous results in a place your organization controls. Because model output varies between runs, one successful trial is weak evidence, and every newly found failure becomes a new case. What Should a Team Do When an AI Vendor Retires Its Model? Treat a vendor's model retirement as a choice between viable alternatives: moving to the successor model, changing the provider, reducing the workflow's scope, reverting temporarily to manual work, or retiring the workflow. Notice periods vary: Anthropic commits to at least 60 days for publicly released models, while OpenAI gives generally available models at least 6 months but may retire faster for safety or compliance reasons. Teams with prepared test evidence can revalidate within that window. Who Should Approve the AI Model Behind a Recurring Workflow? A named workflow owner should be accountable for checking the workflow before each model change and for approving its continued use, even if other people run the tests. In the A3 Delegation System, the AI Definition of Done supplies the standard the workflow is checked against, and the AI Delegation Audit inspects whether this practice works over time; the audit does not gate individual model switches.
Here's the security problem in enterprise AI I'd lose sleep over, and it isn't a model giving a wrong answer. It's a model connected to an identity with enough authority to act on that answer. Think about what an agent really is once it can query a database, call an infrastructure API, update a ticket, and kick off a workflow. It isn't a chat window anymore. It's software that executes things, with credentials, on its own. Most companies still secure it like a web app with a fancy text box. I think that gap is where a lot of future incidents will start. Who Actually Did That? Picture an incident response agent. A pager goes off. The agent pulls telemetry, queries a database, opens a ticket, calls a cloud API, and suggests a fix. Nobody clicked anything between the second step and the fifth. Now try to answer the question an investigator will ask later. Which principal did each of those things? Not who typed the prompt. Whose credential touched the database, with what scope, and who signed off? Microsoft's own guidance is refreshingly blunt about this. It calls out "identity ambiguity": agents running on shared secrets, service principals, or mixed "on behalf of user" setups, so nobody can say for certain which principal is accountable. It also points out that logs tend to record the chat response and miss the tool actions and downstream authorization decisions that matter. You can read it in Least privilege for AI agents with Microsoft Entra Agent ID, updated July 15, 2026. Authentication tells you the agent is who it says it is. It doesn't tell you whether a given action should be allowed. Those are different questions, and agents force us to ask the second one constantly. An App Has Paths. An Agent Makes Them Up. With a traditional app, the logic is fixed when you design it. A user acts, the app calls an API, the API touches data. You can map the paths on a whiteboard. An agent picks its path at runtime. It chooses tools, chains calls, reads results that shape the next call, and sometimes crosses system boundaries while doing it. Microsoft describes agents as planning and executing multistep workflows across systems, sometimes with little or no human involvement. Software like that needs what every other actor in the enterprise already has: an identity of its own, an accountable owner, scoped permissions, a lifecycle, and an off switch. That's the direction Microsoft's Entra Agent ID is heading, treating agents as a distinct identity type instead of recycling ordinary application identities. Here's an overview of agent identities in Microsoft Entra. I'll say the quiet part loudly: the LLM should never be your security boundary. A model can be talked into things, confused, or hijacked by a sentence buried in a retrieved document. Put the boundary where you can enforce it deterministically, around the identity, the tools, and the systems downstream. Authenticated and Still Dangerous An agent can log in flawlessly and still be wildly overprivileged. Take the incident agent again. It needs to read logs, metrics, tickets, and configuration, and it needs to write exactly one thing: an incident ticket. It has no business deleting infrastructure, editing IAM roles, creating admins, exporting customer records, or touching security policy. Microsoft's pattern makes that concrete. Keep the read role for gathering evidence separate from the write role for tickets. Allowlist only "create or update ticket." Block delete and admin actions. Ask a human before any bulk update. The Number Nobody Calculates Permission creep isn't new. Agents just make it sneakier. Microsoft names it "permission creep and excessive aggregate privileges." A team grants a broad role to get a pilot moving and never narrows it later. Or they stack lots of small roles without separating tasks, and the sum ends up far too powerful. Nobody adds it up, so everybody underestimates what the agent can really do. Every grant looks fine on its own. CRM read. Mailbox access. Ticketing. A cloud role. A deployment pipeline. Together they describe a high-privilege operator who never sat through onboarding. So stop asking "is this permission safe?" and start asking "what can this agent do, end to end, with everything combined?" Microsoft's first implementation step is exactly that: inventory your agents and tool integrations and work out their aggregate effective permissions. Every Tool Is a Door The dangerous failures here are boring ones. Microsoft warns that if an agent can call any tool it can find, one prompt injection or workflow bug can set off export, delete, or privilege changes, or chain actions across services. The industry is starting to name this properly. The OWASP GenAI Security Project announced its Top 10 for Agentic Applications on December 9, 2025, covering risks like goal hijack, tool misuse, and identity and privilege abuse. Its ASI03 entry is about agents running on borrowed, overscoped, or long-lived credentials, so a compromised agent inherits far more access than its job needs. Teleport has a readable breakdown. The rule I'd tattoo on every design review: a tool isn't trusted just because an agent asked for it. Microsoft's advice is to deny unreviewed tools, plugins, integrations, and cross-tenant or guest paths by default, and to check authorization again at the downstream system on every call instead of leaning on the orchestrator. Revalidate identity, role, and scope at each hop so one weak integration can't talk its way around the rest. There's a catch, and Microsoft admits it. All of this depends on downstream systems actually rechecking authorization. Where they don't, the risk walks right back in. "On Behalf Of" Is a Boundary, Not a Label When an agent acts as itself, the audit trail is simple. When it acts for Alice, things get interesting. Does it inherit everything Alice can do? It shouldn't. Alice may hold broad rights that one task will never need. The answer is explicit "on behalf of" context, narrower scopes, and a named owner for the agent. Microsoft recommends logging the "on behalf of" user wherever it applies. OWASP's ASI03 describes the flip side: delegated credentials, cached sessions, and implicit identity let an attacker use the agent to do something its owner never intended. Login Isn't the Finish Line Classic IAM asks, "can this identity reach this resource?" Agents need a second question: "should this exact action happen right now?" Microsoft's recommended pattern pairs a stable, lifecycle-managed agent identity with time-limited privileges. That means just-in-time entitlements: temporary role activation, short-lived tokens or approvals, so elevated access exists only for the length of one workflow. For remediation agents, it suggests JIT elevation or approval gates, scoping to specific resource groups, denying subscription-wide rights, keeping rollbacks ready, and requiring step-up controls for destructive actions. Here's the shape of the decision I'd want in front of every tool call: Python def authorize(agent_id, on_behalf_of, tool, action, resource, context): scope = effective_scope(agent_id, on_behalf_of) # computed, never assumed if tool not in allowlist(agent_id): return deny("tool not allowlisted") if action not in scope.allowed_actions(resource): return deny("action outside effective scope") if is_high_impact(action): # delete, export, privilege change return require_approval_or_jit(agent_id, action, resource) return allow(ttl_seconds=300, correlation_id=context.correlation_id) Don't focus on the syntax. Notice where the decision lives: outside the model, per action, with a short lifetime on whatever it grants. A Transcript Isn't an Audit Trail Microsoft spells out what a useful record holds: agent identity, role, effective scope, action, resource, correlation ID, and the "on behalf of" user when there is one. Its suggested success metrics include the share of agent actions that emit those fields and the share of workflows you can trace end to end across the orchestrator, the tools, and the downstream systems. If your SIEM can tell you an agent "answered a question" but can't tell you which API it called under which scope, you have chat history. You don't have telemetry. How Fast Can You Pull the Plug? Most agent programs I read about spend pages on capabilities and one sentence on shutdown. Microsoft treats the stop path as a first-class concern. Test revocation by disabling the agent, rotating credentials, invalidating tokens, and removing stale permissions. Its success factors include mean time to revoke or disable an agent identity, token invalidation included, and the share of environments with a tested kill switch and recovery procedure. Put mean time to revoke on the same dashboard as mean time to detect. If shutting down an agent takes a ticket, an approval, and two days, its autonomy was never really bounded. It was just unobserved. Legacy Makes Everything Harder Agents can't safely automate what an enterprise doesn't understand. Legacy estates love to hide undocumented business logic, creaky APIs, fragmented data, inconsistent identity models, and thin observability. Point an agent at that, and you're handing a fast, tireless actor a map nobody ever finished drawing. That's why identity, integration, observability and governance now sit beside model choice in modernization work, and why vendors in that space are repositioning around agents. On March 3, 2026, Sonata Software said it had been recognized as a Microsoft Frontier Partner, describing an approach that pairs AI agents with human engineering across cloud and AI platforms, AI business solutions and security. Sonata Software announced that it had earned the 2026–2027 Microsoft AI Business Solutions Inner Circle award, marking the company’s sixth Inner Circle recognition, with Microsoft's Niels Jensen saying in the release, "Inner Circle partners represent our top selling partners worldwide" (Sonata's press release). Both items are vendor announcements, so read them as a signal about where the services market is going, not proof of any particular control. The shift is what matters here: modernization is being pitched as preparation for governed autonomy, and governance starts with identity. What I'd Do on Monday Inventory every agent and tool integration, guest and cross-tenant paths included, and work out each agent's aggregate effective permissions.Give every production agent its own identity and a named owner. Retire shared credentials.Swap broad roles for task-scoped ones, and split read from write.Allowlist tools and actions. Put delete, export, and privilege changes behind approval or JIT elevation.Enforce authorization at the downstream system, not just the orchestrator.Emit identity, role, scope, action, resource, and correlation ID for every action, and send it to your SIEM.Run a revocation drill and write down how long it took. The Short Version Nobody's trying to stop companies from giving agents autonomy. The point is to make that autonomy bounded, attributable, and revocable. If an agent can behave like an employee, an application, and an automation system all at once, the real question is why we still secure it as if it were only an application.
If you are responsible for keeping a production system alive, you have probably been pitched an "AI SRE" in the last few months. Maybe more than one. Maybe more than one this week. When we sat down at Bronto to map that space, we ended up with 64 tools across seven camps: pure-play investigation agents, observability platforms with AI built in, incident management tools with AI on top, AIOps and alert correlation, hyperscaler agents like AWS DevOps Agent and Azure SRE Agent, Kubernetes copilots and open source projects, and a long tail of adjacent tools. All of them use the same two words on their landing page, and they solve very different problems. So the first question most teams ask is the classic one: do we buy, or do we build? In our landscape article, we argue that the choice isn't binary. You can go full DIY, build on open source foundations like HolmesGPT or K8sGPT, buy a product and extend it, or buy it as-is. Most teams land somewhere in the middle. In this article, I want to make a different argument for building one, at least once: build to understand what you buy. Even if you never run your own DIY agent in production, putting one together by hand shows you where its answers come from, what it can't see, and why it goes wrong when it does. After building one, you know which questions to ask a vendor, and you know how to get better results from whatever you end up running. That's the profit you should take away from this post. The fun is the building and seeing your agent try to investigate an incident: it might get it wrong, it might get it right, but you'll see how it interacts with your tools and your data. This post is based on a hands-on lab we ran at an AWS and Bronto evening, and everything is available through bronto-community/ai-sre-lab. By the end, you will have a small agent with the following capabilities: reads logs, traces, and metrics through an MCP server,reads the application's source code and commit history through GitHub's MCP server,writes its hypothesis, evidence, and confidence into a GitHub issue. Note that in the lab we use Bronto as the observability backend. I work there, so I am biased to think it is your best option, but you can of course use any other solution. What an AI SRE Is AI SRE is mostly a marketing term. In short, it's an agentic loop pointed at the production system that can answer questions about it and help you troubleshoot. Like any agentic loop, it has inputs on one side (an alert, a question from a human), a model in the middle, tools underneath (mostly MCP servers these days, for telemetry, code, cloud APIs, runbooks), and outputs on the other side (a Slack message, a ticket, a pull request). So, it's an agent like any other. It's what you connect to it that makes it an agent for SRE. The Patient: A Small Online Shop Our AI SRE needs something to investigate. The lab comes with a tiny storefront: four Python services instrumented with OpenTelemetry, plus a payment processor mock standing in for a third party. You can, of course, point the agent directly at your own data. It's read-only, so it is not able to harm your system. What You Need To run this lab, you need the following: A container engine, like Docker DesktopAn AWS account with access to a model on Amazon Bedrock.A Bronto API key (there is a free trial), or another observability backend with an MCP server.A GitHub account and a fine-grained personal access token. It needs to read the contents of your copy of the storefront repo and write issues to it.Optional, for nicer output: jq and glow. You can watch this video to follow along as we walk through each step: Start the Shop Clone the lab and generate the storefront repository. The script builds a small Git history with a handful of commits and tags two releases, v3.1.0 (healthy) and v3.2.0: Shell git clone https://github.com/bronto-community/ai-sre-lab cd ai-sre-lab ./build-storefront.sh Your agent will later read this code through GitHub, so push it to a repository of your own, tags included: Shell cd storefront gh repo create storefront --public --source . --push git push --tags cd .. Then point the Collector at your telemetry backend and bring everything up: Shell cd demo echo "BRONTO_API_KEY=<your key>" > .env make up Note, that demo/collector.yaml ships to Bronto's EU ingestion endpoint. If your account lives in another region, or you want a different backend, that file is the only thing you need to change. Next, run make up, which deploys v3.1.0 and starts the traffic. It prints a message that you should leave it about ten minutes before you do anything else. An investigator with no baseline has nothing to compare against. So, take your time going through the first few next steps so it can build up! Step 1: The Loop All agents start with a basic file that receives prompts, sends them to the model, and returns the results. It's a simple first agent, so here is more or less the code in full: Python import os from bedrock_agentcore import BedrockAgentCoreApp from strands import Agent from strands.models import BedrockModel model = BedrockModel( model_id=os.environ.get("BEDROCK_MODEL_ID", "us.anthropic.claude-haiku-4-5-20251001-v1:0"), region_name=os.environ.get("AWS_REGION") or os.environ.get("AWS_DEFAULT_REGION", "us-west-2"), ) app = BedrockAgentCoreApp() @app.entrypoint def invoke(payload: dict) -> dict: agent = Agent(model=model) return {"result": str(agent(payload.get("prompt", "Hello!")))} if __name__ == "__main__": app.run() # POST /invocations, GET /ping on :8080 Two libraries do the work. Strands Agents runs the agent loop: send the prompt to the model, run any tool the model asks for, feed the result back, repeat until the model has an answer. The Bedrock AgentCore SDK wraps that in an HTTP server with the /invocations and /ping contract AgentCore Runtime expects. Today that runs on your laptop. Later, the same container can run on AgentCore Runtime without changes. Every step of the lab is a prebuilt image, so you don't need to build anything. Create a .env next to where you run the commands: Shell AWS_DEFAULT_REGION=us-west-2 AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... AWS_SESSION_TOKEN=... BEDROCK_MODEL_ID=us.anthropic.claude-haiku-4-5-20251001-v1:0 With this setup, you can start the agent for the first time: Shell docker run --rm -p 8080:8080 --env-file .env ghcr.io/bronto-community/ai-sre-agent:step-1 Open a second terminal and ask it something: Shell curl -s localhost:8080/invocations -d '{"prompt": "Who are you?"}' | jq -r .result It will say, "Claude, an AI assistant made by Anthropic." Correct, and completely useless for incident response. Right now this is a model behind an endpoint, with no identity and no tools. Step 2: Identity The second step changes only one line of code. Every Markdown file in prompts/ becomes part of the system prompt: Python SYSTEM_PROMPT = "\n\n".join(p.read_text() for p in sorted(Path("prompts").glob("*.md"))) @app.entrypoint def invoke(payload: dict) -> dict: agent = Agent(model=model, system_prompt=SYSTEM_PROMPT) ... The image ships with two files. role.md: Markdown You are the on-call SRE for Storefront, an online shop. You investigate production incidents: what broke, where, and why. And rules.md: Markdown - Only state what you can back with evidence from your tools. - If you have no tool that can answer, say so and name what you would need. - Be brief. You also get to add your own. Create a my.md: Markdown - Answer in at most three bullet points. - End every answer with your confidence: low, medium or high. - Sign off as "your friendly on-call dino". Start step 2 as follows. The command contains your custom instructions as an additional volume: Shell docker run --rm -p 8080:8080 --env-file .env \ -v "$PWD/my.md:/app/prompts/my.md" ghcr.io/bronto-community/ai-sre-agent:step-2 Shell curl -s localhost:8080/invocations -d '{"prompt": "Checkout is slow. What is wrong?"}' | jq -r .result You should get a short answer that says it has no access to telemetry, rates its own confidence as low, and signs off as a dino. That's a good result. The rule "say so and name what you would need" did its job: an agent that admits it can't see anything is far more useful than one that guesses. Step 3: Eyes Now the agent gets something to look at. Step 3 adds one tool source, Bronto's MCP server: Python bronto = MCPClient(lambda: streamable_http_client( os.environ.get("BRONTO_MCP_URL", "https://mcp.eu.bronto.io/mcp"), http_client=httpx2.AsyncClient( headers={"X-BRONTO-API-KEY": os.environ["BRONTO_API_KEY"]}, timeout=60, ), )) @app.entrypoint def invoke(payload: dict) -> dict: agent = Agent(model=model, system_prompt=SYSTEM_PROMPT, tools=[bronto]) ... That's the whole change. The MCP server's tools (search logs, list datasets, and so on) become tools the agent can call, and Strands handles the plumbing. This is also the point where MCP pays off: if your telemetry lives somewhere else, you swap this client for that vendor's MCP server and keep everything else. Add BRONTO_API_KEY to your .env (and BRONTO_MCP_URL if your account isn't in the EU region), then: Shell docker run --rm -p 8080:8080 --env-file .env \ -v "$PWD/my.md:/app/prompts/my.md" ghcr.io/bronto-community/ai-sre-agent:step-3 Start with a question that tells you what it can see: Shell curl -s localhost:8080/invocations -d '{"prompt": "What services do you know about?"}' | jq -r .result It should list the storefront services. Go ahead and ask it some more questions about the state of those services: what HTTP endpoints are available? What is the average error rate right now? With this, you have a first working version. Next we want to investigate an incident. To do so, ship the next release of the storefront: Shell make release According to the Makefile, symptoms take about 60 seconds to show up in p95. So wait a minute or two and then ask it: Shell curl -s localhost:8080/invocations -d '{"prompt": "Anything wrong with checkout?"}' | jq -r .result It will come back with a hypothesis about what is wrong and what you might be able to do about it. Take a look at the telemetry yourself and check: is the analysis correct, or did the agent pick up some false information? Step 4: Mouth An answer in your terminal is nice for a demo, but in production you would want to have it sent to a Slack channel, a pager app, or an issue tracker. In our example, we send the answer as a GitHub issue. This would let you tag your coding agent to review the issue and open a pull request that fixes it. You now have two options for how this gets filed. Either you give your agent another tool, and it can decide for itself where to send the hypothesis, or you make the code file the issue, so every analysis gets pushed into a dedicated issue: Shell def file_issue(question: str, hypothesis: str) -> str: r = httpx2.post( f"https://api.github.com/repos/{os.environ.get('GITHUB_REPO', 'ai-sre-lab/storefront')}/issues", headers={"Authorization": f"Bearer {os.environ['GITHUB_TOKEN']}"}, json={"title": f"[investigation] {question}"[:120], "body": hypothesis}, timeout=30, ) r.raise_for_status() return r.json()["html_url"] @app.entrypoint def invoke(payload: dict) -> dict: question = payload.get("prompt", "Hello!") agent = Agent(model=model, system_prompt=SYSTEM_PROMPT, tools=[bronto]) hypothesis = agent(question) return {"result": file_issue(question, hypothesis)} To make sure that what the agent provides fits the output, an additional new prompt file tells the agent how to write it: Markdown Your answer is filed as a GitHub issue for the on-call team. Write it as one: a one-line hypothesis, the evidence for it, your confidence, and what you could not check. Before running the next version of your agent, add your GitHub token and your repository to .env: Shell GITHUB_TOKEN=github_pat_... GITHUB_REPO=<your-user>/storefront Run step 4: Shell docker run --rm -p 8080:8080 --env-file .env \ -v "$PWD/my.md:/app/prompts/my.md" ghcr.io/bronto-community/ai-sre-agent:step-4 Ask it again to investigate the issue: Shell curl -s localhost:8080/invocations -d '{"prompt": "Anything wrong with checkout?"}' | jq -r .result The response is now a link. Open it and read the hypothesis. Is it right? How confident is it? There's a good chance it's confidently wrong. While testing the lab, one run concluded that checkout was down because a query returned nothing: an empty result is not proof of an outage, but nothing told the agent that. Step 5: Better Instructions What you do next doesn't involve code. You do what you'd do with a new human on the rotation: you tell them how you investigate. Add these lines to your my.md: Markdown - Slow is broken too: compare latency (p50, p95) before and after, not only errors. - Compare against a quiet window earlier the same day. - Look for `deploy` spans near the onset: they name the commit that went live. Each line encodes a habit experienced SREs have, and models don't bring by default. Checkout can be very broken without throwing a single error. A number means little without a baseline. And the first question in most incidents is "what changed?" The prompt files are read when the container starts, so restart step 4 with the same command and ask a more realistic question: Shell curl -s localhost:8080/invocations \ -d '{"prompt": "Customers say checkout got slow in the last 30 minutes. What is going on?"}' | jq -r .result Compare the new issue with the old one. Is it better? Worse? Did it fail outright? Step 6: Better Model As you might now, a different model can create a different output, so if you are not satisfied with the results yet, change one line in .env: Shell BEDROCK_MODEL_ID=us.amazon.nova-lite-v1:0 Restart your agent, ask the question again, and compare the outputs again: better or worse? Step 7: Code So far the agent can see that something changed and maybe even when. If your instructions worked, it found the deploy. What it can't do is look at what was deployed. Step 7 adds the second MCP server, GitHub's, restricted to read-only repository tools: Python github = MCPClient(lambda: streamable_http_client( os.environ.get("GITHUB_MCP_URL", "https://api.githubcopilot.com/mcp/x/repos/readonly"), http_client=httpx2.AsyncClient( headers={"Authorization": f"Bearer {os.environ['GITHUB_TOKEN']}"}, timeout=60, ), )) @app.entrypoint def invoke(payload: dict) -> dict: question = payload.get("prompt", "Hello!") agent = Agent(model=model, system_prompt=SYSTEM_PROMPT, tools=[bronto, github]) ... To make it useful to the agent, add one more prompt file, code.md. It connects the telemetry to the code: Markdown The shop's source code is in the GitHub repository `ai-sre-lab/storefront`. Every service reports the commit it runs as `deployment.commit`. Replace the repository path with your own, then mount it as an additional volume: Shell docker run --rm -p 8080:8080 --env-file .env \ -v "$PWD/my.md:/app/prompts/my.md" \ -v "$PWD/code.md:/app/prompts/code.md" \ ghcr.io/bronto-community/ai-sre-agent:step-7 Ask the same question again: Shell curl -s localhost:8080/invocations \ -d '{"prompt": "Customers say checkout got slow in the last 30 minutes. What is going on?"}' | jq -r .result Does it find the deploy? Does it open the release and pick the right commit? In our testing, it found the deploy marker and the commit, and then stopped. The release contains several commits, and the last hop, reading every one of them and figuring out which change explains the symptom, didn't happen on its own. If you experience the same, try to fix it yourself by refining your system prompts or by trying yet another model. When you're done, make rollback puts the healthy version back, and make down cleans everything up. If you want to give your agent a harder case, make psp-slow degrades the third-party payment processor. So, Buy or Build? Now you know what an AI SRE is and how it works, from the inside. That's a much better position from which to answer the question this post started with. If you buy, a lot of what hurt along the way becomes someone else's problem: confidently wrong answers that need endless prompt tuning, context windows overflowing with search results, wiring up every integration yourself. AWS DevOps Agent, for example, starts investigating when an alert fires and connects to the tools you likely already run, and you can still extend it with custom skills and your own tools. Take the four questions from the landscape article with you into every demo: Where does it get its data? Does it act, or only advise? Can you see its reasoning? What happens when it's wrong? After this lab, you'll know what good and bad answers to those look like. If you build, what you have now is a skeleton, and you can build more features towards a complete picture on top of it: Let alerts trigger it instead of curl.Run it on AgentCore Runtime instead of your laptop (agentcore deploy).Give it more tools: your cluster, your cloud APIs, your past incidents and postmortems.Observe the agent itself. Its own traces tell you which tools it called, how many tokens it burned, and where it went wrong, and that's the input you need to improve it. Either way, the data underneath matters more than the agent on top. Every improvement in this lab depended on the telemetry being there: a baseline from ten quiet minutes, latency and not just errors, a deployment.commit attribute that connects a span to a line of code. An agent can only reason about what your system tells it. That was true for humans long before agents showed up. So: what would your agent get wrong? The full lab, including the slides, the agent images for every step, and the storefront harness, is at github.com/bronto-community/ai-sre-lab. Content is CC BY 4.0; code is MIT. If you build something on top of it, I'd love to hear about it. I've shown how easy it is to build a simple AI SRE agent for fun. If you want to see what a production-ready one looks like, read our post on the Bronto blog, Introducing Bronto's Open-Source Alert Investigation Agent. It's an open-source agent that replicates the Alert Investigation feature in Bronto, and it's essentially our production version of this lab: a Bronto monitor triggers it instead of curl, it sticks to a constrained set of tools and reasoning paths instead of improvising, and it hands you a report with likely root causes and suggested next steps. The code is at bronto-community/bronto-alert-investigation-agent.
Agents Can Communicate, But Do They Understand Each Other? Two agents. Same customer ID. Different decisions. That is the semantic gap hiding inside most multi-agent enterprise deployments today — and protocols like MCP and A2A alone cannot close it (nor will they ever). AI agents are getting better at interacting through APIs, events, messages, and shared protocols. They can exchange data, invoke services, and coordinate tasks across enterprise systems. But communication doesn’t guarantee understanding. Imagine three agents dealing with the same customer request. One sees a customer as an account holder, another as a billing entity, and a third as a CRM contact. Data is exchanged, but each agent interprets it differently. This exposes a fundamental challenge in multi-agent enterprises: agents can exchange information without sharing the same meaning. Protocols define how information is exchanged. APIs define what data is exchanged. Neither defines what enterprise concepts such as customer, product, entitlement, incident, or approval actually mean. As organizations deploy specialized agents in sales, finance, ops, security, and engineering, semantic consistency is paramount. Agents need more than connectivity — they need a shared understanding of business concepts, relationships, and constraints. “Agent interoperability is not only a protocol problem; it is a semantic problem.” The Semantic Gap in Multi-Agent Enterprises In a multi-agent enterprise, different agents are built by different teams, trained on different data sets, connected to different systems, and designed around different business contexts. They may all exchange valid JSON messages, call the same APIs, or participate in the same workflow but still interpret the underlying business concepts differently. This is the semantic gap: what’s different between exchanging data and agreeing on what that data means? For example, the term customer may refer to a: CRM contact for a sales agentBilling account for a finance agentService subscriber for a support agentLegal entity for a compliance agent Similarly, priorities, incidents, owners, entitlements, or approvals may have different meanings in systems and domains. These differences are manageable when humans are involved because people infer context, ask clarifying questions, and reconcile ambiguity. Autonomous agents cannot do this reliably unless the semantics are explicitly represented. Without shared semantics, multi-agent systems can suffer from: Inconsistent interpretations of the same enterprise dataIncorrect agent-to-agent handoffsDuplicated or conflicting decisionsBrittle mappings between systemsGovernance rules that are applied differently across agents The challenge therefore moves beyond technical interoperability. Enterprises need semantic interoperability — a common model of concepts, relationships, constraints, and vocabulary that gives every participating agent the same frame of reference. That semantic foundation is provided by a shared enterprise ontology. What Is a Shared Enterprise Ontology? A shared enterprise ontology is a common semantic model that describes the concepts an enterprise uses (and how they are related to each other), as well as rules that give meaning to those concepts. It gives business knowledge a machine-readable format so that people, applications, and AI agents interpret enterprise information consistently. An ontology may define concepts such as: CustomerProductOrderServiceIncidentEntitlementEmployeeApproval More importantly, it defines how these concepts relate. For example: Customer → purchases → ProductCustomer → owns → AccountProduct → provides → ServiceIncident → affects → ServiceEmployee → approves → Request This is different from simply maintaining a common vocabulary. An ontology captures meaning, relationships, hierarchy, and constraints. A shared enterprise ontology thus becomes a semantic reference layer that agents can use to interpret data from different systems in the same way. Instead of each agent deciding what a customer, incident, or approval is, the enterprise defines those concepts once and reuses them across the enterprise. For multi-agent systems, this shared semantic model can become the common language that enables agents not only to exchange information but also to reason about it consistently. Why APIs, MCP, and A2A Are Not Enough on Their Own APIs, MCP, and A2A are examples of how interoperability problems are solved. Agents discover capabilities; they exchange messages; invoke tools; coordinate actions across systems. But they are more about connectivity and interaction than shared meaning. An API can have a field called customer_id. MCP can expose a tool to get customer data. An A2A interaction can send that information from one agent to another, but none of these mechanisms by themselves guarantees that every participating agent will interpret customer, account, service, or entitlement in the same way. This distinction matters. APIs specify how applications exchange data and invoke functions.MCP standardizes how models and agents access tools, resources, and context.A2A allows agents to communicate, delegate, and collaborate. These mechanisms provide technical interoperability, but semantic interoperability requires an additional layer: a common understanding of enterprise concepts and relationships. For example, two agents may exchange an incident object through an API or agent protocol, but one interprets an incident as a customer support ticket and the other an operational outage. Technically, they succeed in communication, but the decision made may still be wrong. An ontology for shared enterprise complements APIs, MCP, and A2A by specifying the semantic contract behind the information exchanged. In that model: APIs provide access.MCP provides tool and context interoperability.A2A provides agent collaboration.Ontology provides shared meaning. Together, these layers create a stronger foundation for reliable multi-agent enterprise systems. What Should an Agent-Aware Enterprise Ontology Describe? A traditional enterprise ontology describes business concepts (customers, products, services, orders, assets, and incidents). An agent-aware enterprise ontology should also go further by describing the agents that operate on those concepts. At minimum, it should capture five areas: Enterprise entities – customer, product, service, account, incident, policy, asset, employee.Relationships – owns, depends on, affects, approves, belongs to, consumes, manages.Agent capabilities – what an agent can search, analyze, create, modify, approve, or execute.Permissions and constraints – what an agent is allowed to access or change, under which conditions.Operational context – which system owns the data, its sensitivity, lifecycle state, provenance, and applicable governance rules. For example, the ontology could say that a Support Agent can read customer entitlement data; create an incident; recommend a resolution — but cannot approve a refund above some threshold. A Finance Agent can access billing records and authorize certain financial actions. This is what makes the ontology useful not only for understanding enterprise data but also for understanding who can act on that data, how they can act, and under what constraints. An agent-aware ontology can therefore answer questions like: What does this concept mean?Which agent owns this capability?What data can the agent access?Which actions are permitted?What policies apply before execution? This turns the ontology from a passive knowledge model into a semantic foundation for agent discovery, coordination, authorization, and governance. From Skill Discovery to Semantic Capability Discovery Most agent platforms can already discover skills or tools: search a catalog, inspect a description, and invoke a capability. The limitation is that skill discovery is usually done based on names, keywords, or interface descriptions. An agent may find a tool called create_ticket, but still not understand: What type of ticket it createsWhich business entity the ticket relates toWhat prerequisites applyWhat permissions are requiredWhether another capability is semantically equivalent This is where semantic capability discovery becomes important. Instead of asking only: “Which skill matches this request?” an agent can ask:“Which capability can perform this business action on this enterprise entity under these constraints?” For example, an ontology could describe that: RefundProcessingAgent → canPerform → IssueRefundIssueRefund → appliesTo → CustomerOrderIssueRefund → requires → ApprovedReturnIssueRefund → governedBy → RefundPolicy Now the agent isn’t finding a skill by name alone. It is finding a capability based on meaning, relationships, prerequisites, and policy context. This is especially useful when multiple agents expose overlapping capabilities (one agent may support refunds on retail orders, another on subscriptions, and another only for low-value transactions). Semantic metadata lets the orchestrating agent choose the right capability based on business context rather than just string matching. In this model, the ontology becomes a semantic capability graph connecting: Agent → Capability → Business Entity → Preconditions → Policies → Constraints This enables richer agent discovery, better routing, safer composition, and more reliable delegation across the enterprise. Ontology-Driven Agent Selection and Governance As enterprises deploy more specialized agents, choosing the right agent gets harder. A request may match several agents, but not every agent will have the same capability, authority, data access, or policy constraints. An enterprise ontology can make this selection more intelligent. Instead of routing a request based only on keywords or static configuration, an orchestrator can use semantic relationships such as: Agent → hasCapability → ApproveRefundApproveRefund → appliesTo → CustomerOrderAgent → authorizedFor → RegionCapability → constrainedBy → RefundPolicy When a task arrives, the system can evaluate not only which agent can perform it, but also: Whether the agent has the required capabilityWhether it can access the relevant enterprise dataWhether it is authorized for the requested actionWhich policies and constraints applyWhether human approval is required For example, two agents can both process refunds - one may be limited to transactions below a defined threshold, while another may handle high-value refunds but require managerial approval. The ontology provides the semantic context needed to route the request correctly. The same model can also support governance. Policies can be directly associated with business entities, capabilities, roles, and actions, so agents can reason about constraints before execution. This creates an ontology-driven decision flow: Request → Business Intent → Required Capability → Eligible Agents → Policy Evaluation → Selected Agent → Execution The result is more than smarter routing. It enables policy-aware, context-aware, and explainable agent selection across the enterprise. Building a Minimal Agent-Aware Enterprise Ontology AgentsCapabilitiesEnterprise entitiesPolicies and constraints Consider a simple refund-processing scenario. An enterprise has a support agent that can process refunds for customer orders, but that capability is governed by a refund policy. A minimal semantic model could look like this: This can be represented using RDF/OWL-style semantics. For example, using Turtle: Turtle @prefix ex: <http://example.com/enterprise#> ex:SupportAgent a ex:Agent ; ex:hasCapability ex:ProcessRefund ; ex:accesses ex:CustomerAccount ex:ProcessRefund a ex:Capability ; ex:appliesTo ex:CustomerOrder ; ex:governedBy ex:RefundPolicy . ex:RefundPolicy a ex:Policy ; ex:maxAutomaticRefund "500" Even this small ontology gives an orchestrating agent more information than a conventional tool catalog. Instead of discovering only process_refund(order_id), the agent can understand that the capability: Operates on a CustomerOrderIs provided by the SupportAgentDepends on access to customer informationIs governed by a specific refund policy The next step is to query the ontology. For example, an orchestrator could ask: SQL SELECT ?agent WHERE { ?agent ex:hasCapability ex:ProcessRefund . } The result identifies agents that semantically provide the required capability. A richer query could also include policy and business context: SQL SELECT ?agent ?policy WHERE { ?agent ex:hasCapability ?capability . ?capability ex:appliesTo ex:CustomerOrder . ?capability ex:governedBy ?policy . } This creates the foundation for semantic agent selection. The important point is that the ontology does not replace APIs, MCP tools, or agent protocols. It sits above them as a semantic decision layer. The ontology determines: What does the request mean?Which capability is required?Which agent provides it?Which enterprise entity is affected?Which policy applies? The execution layer can then use an API, MCP tool, or A2A interaction to perform the actual action. For a production environment, this minimal model can gradually expand to include concepts such as roles, data sensitivity, regions, approval thresholds, provenance, dependencies, risk levels, and human-approval requirements. The key is to start small. A handful of well-defined enterprise concepts and relationships can already move agent orchestration from simple tool matching toward semantic, policy-aware capability discovery. Where This Architecture Fits in the Emerging Agent Stack The ontology-driven architecture fits between the agent reasoning layer and the execution layer of the emerging enterprise agent stack. A typical enterprise agent stack may include: User or application layer – where requests originateAgent/orchestration layer – interprets intent and coordinates workSemantic layer – maps intent to enterprise concepts, capabilities, policies, and eligible agentsInteraction layer – MCP, APIs, A2A, events, and messagingEnterprise systems layer – CRM, ERP, ITSM, data platforms, and internal services The shared enterprise ontology belongs primarily in the semantic layer. Its role is not to replace the LLM, agent framework, MCP server, API gateway, or A2A protocol. Instead, it provides the semantic context needed before those components are used. This separation is important because each layer solves a different problem. The reasoning layer determines what the user is asking.The ontology layer determines what that request means within the enterprise.The orchestration layer determines which agent should handle it.The interaction layer determines how the selected agent or tool is invoked.The enterprise systems layer performs or records the actual business action. As agent ecosystems become more distributed, this semantic layer can act as connective tissue across otherwise independent agent platforms. Different agents may use different models, frameworks, protocols, or runtime environments while still relying on the same enterprise definitions of capabilities, entities, and policies. The architecture therefore adds a missing layer to the emerging agent stack: semantic interoperability between reasoning and execution. Challenges: Ontology Evolution, Ownership, Federation, and Governance A shared enterprise ontology improves semantic interoperability but also brings its own operational and governance problems. Enterprise concepts are not fixed: products change, organizational structures evolve, regulations shift, and new agents bring new capabilities; the ontology must therefore evolve without breaking existing consumers. Ontology Evolution In a federated ontology landscape, a change in one domain propagates to the entire semantic layer. Changing CustomerAccount in the Customer/CRM ontology, tightening the Entitlement definition in the Product ontology, or adding a new relationship between Incident and Risk in the IT and Operations domain can affect every agent that reasons over those concepts (sometimes not immediately visible). A database schema change usually only affects one system, whereas an ontology change can impact how a sales agent qualifies a lead, how a support agent resolves a ticket, how a finance agent authorizes a payment, and how a compliance agent evaluates a policy, all at the same time. The blast radius is wide because the semantic layer is shared. Ontology evolution therefore needs practices borrowed from API lifecycle management: Versioning – URI-based version identifiers on classes and relationships (for example, ex:v2/CustomerAccount) so that agents can declare which ontology version they depend on.Backward compatibility – additive changes are preferred; breaking changes require a deprecation period with the old and new definitions coexisting.Deprecation policies – a defined timeline for retiring concepts, with explicit successor mappings so consuming agents can migrate incrementally.Change impact analysis – before publishing a change, tooling should identify which agents, tools, and downstream applications reference the affected concepts.Validation before rollout – semantic regression tests that verify existing agent queries and capability graphs still resolve correctly against the new version. Agents should declare which ontology version they are using, and orchestrators should be able to route requests to agents that share a compatible semantic baseline. This prevents a situation where two agents with different ontology versions interpret the same concept differently — which is precisely the problem the ontology was introduced to solve. Ownership A central question is: who owns the meaning of enterprise concepts? The answer is rarely the team that builds the ontology infrastructure. A platform or architecture team may maintain tooling, graph store, versioning pipeline, and publishing process — but it shouldn’t define what Customer, Risk, Incident, Entitlement, or Approval mean independently of those concepts. Those definitions carry business, legal, and operational weight. Semantic ownership should be closer to the business domain. Customer/CRM ontology should belong to teams that run CRM processes and understand what a customer relationship means commercially; Finance ontology should be owned by finance and accounting because they know the difference between an Invoice, Payment, Cost Center, and Financial Account; Security ontology (Identity, Role, Permission, Policy, and Risk) should belong to security teams who understand the compliance implications of each concept. This model (central semantic governance with distributed domain ownership) is how platform engineering works at scale. The platform team sets standards, tooling, and alignment rules across domains. Domain teams set meaning within their area. Neither can override the other unilaterally. In practice, this means having ownership metadata on every ontology concept: who owns it (team), who is the subject-matter expert, and which review process applies when that definition needs to change. If not, the ontology becomes either a bottleneck controlled by one central team or an inconsistent patchwork where every team modifies concepts without coordination. Federation Trying to force all of this into one monolithic ontology isn’t practical. Governance bottleneck; slows down domain teams; model is too abstract to be useful for any specific domain. The diagram above shows a scalable alternative: federated ontology design. Each domain has its own ontology (Customer/CRM, Finance, Product, IT and Operations, Security and HR) — they have full autonomy over the concepts, relationships, and terminology in that domain. Ontologies for each domain link to an Enterprise Ontology Core shared by all domains via explicit semantic mappings and alignment relationships. The core contains cross-domain concepts, shared vocabularies, and governance and versioning rules that make federation work. This architecture also extends outward in two directions. On one side, the enterprise core aligns with external industry ontologies — schema.org for general web semantics, GS1 for product and supply chain standards, FIBO for financial industry terminology, SNOMED CT for healthcare — allowing the enterprise to adopt established standards rather than reinventing definitions. On the other side, partner and ecosystem ontologies for suppliers, regulatory bodies, and industry-specific frameworks can federate with the core through controlled extension points. The goal is not to eliminate domain-specific meaning. It is to make the relationships between those meanings explicit and machine-readable, so that an agent operating in the Finance domain and an agent operating in the Customer domain can each reason within their own semantic context while still communicating consistently when their work intersects. Federation also means that new domains can be onboarded incrementally. A new AI agent introduced for HR or procurement does not require a redesign of the entire ontology. It connects through the same alignment and mapping pattern, inheriting cross-domain concepts while adding its own domain vocabulary. Governance Because AI agents use ontology definitions to make autonomous operational decisions, semantic changes are no longer just documentation updates — they are configuration changes with real business consequences. Changing the definition of Entitlement may cause a support agent to deny services it should approve. Altering the Policy concept may cause a finance agent to bypass a control it previously enforced. The ontology is live operational infrastructure. Governance must therefore be treated with the same rigor applied to production software releases. At minimum, it should define: Who can propose changes – any domain team can propose additions or modifications within their domain, but cross-domain changes require joint review.Who approves semantic changes – changes to core enterprise concepts should require approval from the relevant domain owners and a central semantic governance board.How conflicts between domains are resolved – when two domain teams define the same concept differently (for example, both Finance and CRM define Account), there must be a defined arbitration process that results in either a canonical definition or an explicit mapping.How provenance is recorded – every concept should carry metadata about who introduced it, when, why, and which version it appeared in, so that an audit trail is always available.How policy-related concepts are reviewed – concepts that directly govern agent behavior, such as approval thresholds, permission levels, and compliance rules, should require review by legal, compliance, or risk teams before they are published.How changes are tested against existing agent workflows – before a semantic change is released, it should be validated against a test suite of representative agent queries and orchestration flows to confirm that existing behavior is not unintentionally altered. For high-impact concepts, ontology updates should require the same level of review as a production policy change or a regulated configuration update. The bar is not arbitrary: if an agent can take a financial action, restrict access, or escalate an incident based on an ontology definition, then that definition carries the same operational weight as the code or policy that governs the same action. Ultimately, the challenge is not just building a shared ontology. It is maintaining a trusted semantic contract across teams, systems, and agents as the enterprise continuously changes. The federated architecture distributes that responsibility appropriately — each domain team owns what they understand, the core team maintains coherence, and governance ensures that changes are deliberate, reversible, and traceable. “A shared ontology is only valuable if its meaning remains governed, traceable, and trustworthy as the enterprise evolves.” Conclusion In the multi-agent enterprise, communication is only the first step. True collaboration requires a shared understanding of business meaning. Protocols connect agents; ontologies align them. As AI ecosystems grow, semantic interoperability will become as important as technical interoperability. The challenge will no longer be whether agents can communicate, but whether they understand enterprise concepts well enough to collaborate safely, consistently, and effectively. A practical starting point is simple: model three things, your key business entities, the agents that operate on them, and the policies that govern those interactions. The ontology can evolve incrementally as the agent ecosystem grows. The future of enterprise AI will depend not only on smarter agents, but on agents that share a common understanding of the enterprise they serve.
I got interested in the AI Software Factory concept because it asks a much bigger question than “How can I write code faster?” It asks how AI agents can help move an idea through the entire software development lifecycle, from planning and implementation to testing, deployment, monitoring, and learning. That difference matters. Coding assistants are already useful, but generating code is only one part of building software. I still need to understand the service, validate the change, get the right approvals, and keep production healthy. When I started researching how companies like Uber approach agent-driven development, the infrastructure behind the agents fascinated me more than the code generation itself. The real opportunity is not a collection of clever tools working independently. It is a coordinated system that gives those tools context, boundaries, and a reliable path to production. What I Mean by an AI Software Factory I think of an AI Software Factory as an assembly line for software, with specialized agents handling different jobs and humans controlling the decisions that carry meaningful risk. The factory starts with developer intent and ends with verified software running in production, with operational feedback returning to the beginning. The manufacturing analogy helps me explain it. A car factory does not rely on one machine to perform every task. Different stations have specific responsibilities, and the assembly line determines how work moves between them. Software needs the same kind of coordination. An AI Software Factory can include agents for planning, coding, review, testing, security, release verification, deployment, and monitoring. But the agents alone do not make it a factory. The operating layer needs to connect their work, enforce policies, and expose what happened at each stage. Uber was one of the examples that drew me into this topic. The research I explored described agents handling more than 70% of the company’s pull requests. What interested me most was the supporting infrastructure: agents need to understand systems, run validation, and help maintain software at scale, not simply produce changes. That is the distinction I keep coming back to. The factory is the system around the agents, not just the agents themselves. Faster Coding Does Not Automatically Mean Faster Delivery I am excited about tools like GitHub Copilot and Cursor, but I do not confuse faster syntax generation with faster software delivery. If coding gets dramatically faster while everything after it stays the same, the bottleneck simply moves downstream. More code arrives in testing. More pull requests land in review queues. Senior engineers spend more time evaluating changes, and deployment processes still have the same constraints. The team can feel incredibly productive while the amount of reliable software reaching production barely changes. This is the problem an AI Software Factory is supposed to address. Optimizing one stage is not enough when delivery depends on the whole pipeline. I find it useful to separate two questions: How quickly can I generate a change? Coding assistants can help significantly here.How reliably can I deliver that change? This depends on context, testing, review, approvals, deployment, and operations. The second question is where the broader architecture becomes important. A bigger pile of generated code is not the outcome I want. I want useful changes that pass validation, fit the system, and reach production safely. For me, the value of an AI Software Factory lies in improving that complete flow rather than celebrating raw code volume. Governance Is What Separates a Factory from Agentic Chaos There is a risky version of this story: I add several autonomous agents to the development lifecycle, give them access to tools, and assume the result will be efficient. Without a common operating layer, that can become agentic chaos. When something breaks, I need answers. Which agent changed the service? What requirements and business context did it use? Which checks passed? Who approved the release? If those answers are missing, faster execution has made the system harder to control. A governed AI Software Factory makes that information visible and makes its boundaries enforceable. I want explicit inputs, defined output destinations, security rules, and approval gates that agents cannot quietly bypass. Earlier approaches such as infrastructure as code and GitOps helped automate infrastructure and deployment workflows. Agent-driven development extends automation into planning and implementation, which makes governance across the lifecycle even more important. My preferred division of responsibility is straightforward: agents perform focused work, while humans define the rules and authorize consequential decisions. An agent should not decide what business risk is acceptable. That is why I do not see human governance as the opposite of automation. In an AI Software Factory, governance is what makes broader automation usable. I Start with Service Context, Then Route Work to Specialists Before generating a single line of code, I want the factory to fetch the service context. That means knowing who owns the service, which systems it depends on, what requirements apply, and which policies govern the change. Without that foundation, an agent can produce an implementation that looks reasonable in isolation but does not fit the organization’s actual system. The initial context is not administrative overhead. It is part of the engineering input. I also would not hand an entire feature request to one giant prompt and ask a single model to do everything. Planning, implementation, review, and operations are different responsibilities. Mixing them together makes it harder to isolate mistakes and understand the output. In an AI Software Factory, I prefer a constrained handoff: Gather context: Resolve ownership, dependencies, requirements, and applicable rules.Create a plan: A planning agent maps the architecture and implementation approach.Approve the plan: A human checks the proposed direction before implementation begins.Build the change: A coding agent executes the approved, bounded plan.Validate the output: Review, testing, and security responsibilities follow through their own stages. These boundaries help contain errors rather than allowing an unsupported assumption to travel unchecked through every phase. They do not make hallucinations impossible, but they create clearer places to detect and stop them. That narrow division of labor is one of the most useful design ideas in the AI Software Factory model. CI and Human Approval Must Be Real Gates Once generated code moves forward, I still want the traditional continuous integration machinery to do its job. AI does not remove the need for builds, automated tests, or security validation. My rule is simple: a failed CI build blocks progression toward deployment. It should not become an advisory message that an agent can ignore because it thinks the change is probably fine. An AI Software Factory needs those checks wired into workflow control. For background on the underlying practice, GitHub’s continuous integration documentation explains how automated builds and tests support validation of repository changes. Passing CI is necessary, but it is not the same as permission to release. After automated validation, the workflow reaches a human review gate and pauses until someone explicitly authorizes the next step. At that gate, I want to evaluate architectural integrity, release readiness, and acceptable risk. The emphasis shifts away from spending all my attention on routine syntax checks and toward the questions that require engineering judgment. That does not mean I stop examining code when necessary. It means the factory should handle repetitive validation so that my review can focus on whether the change belongs in the system and whether it is safe to proceed. For me, an AI Software Factory protects speed by putting human judgment exactly where the stakes justify it. The Factory Continues After Deployment I do not consider deployment the finish line. Once a human approves the release, a delivery agent can move the change into production, but the workflow needs to continue into operations. A monitoring agent then checks live service health and looks for degradation after deployment. If health drops, incident response should follow predefined rules rather than depend on an agent improvising a recovery strategy. In the AI Software Factory model I explored, those responses include creating incident tickets, notifying the responsible team in Slack, and triggering predefined rollbacks. Service ownership and incident policies matter here just as much as they did during planning. The final piece is the feedback loop. Production signals and deployment outcomes need to flow back into the service context used for future work. I find this especially important because a pipeline that only moves forward is still largely a static automation sequence. A pipeline that brings operational results back to its starting point can improve the information available for the next plan. When I describe an AI Software Factory as learning, this is what I mean: deployment results and live system behavior inform subsequent work. I am not suggesting that agents should rewrite their own policies or expand their authority. The feedback improves context. Humans still own the boundaries. A Practical AI Software Factory Playground With Port To make the architecture concrete, I used a playground built around a customer support API. The developer intent was to build an API that summarizes tickets, stores conversation history, exposes REST endpoints, and can be safely deployed to production. I like this example because the request is more than a coding task. It includes functionality, persistence, an interface, and a delivery expectation. An AI Software Factory has to carry all of that intent through the lifecycle. In the playground, Port sits above the factory floor as the agentic SDLC layer. It supplies organizational context and connects agent and skill registries, workflows, policies, guardrails, and human gates. The visible stages run from intent and context through planning, building, reviewing, testing, security, release verification, deployment, post-deployment verification, and monitoring. An agent console and activity log expose the sequence of actions. When I ran the demo, the workflow encountered a human gate after planning and another before deployment. After approval, it continued through post-deployment verification and monitoring. The completed run showed 10 agents completed, 13 checks passed, two human gates, and a low release-risk indicator. I treat those numbers as the outcome of that illustrative run, not evidence that every release will be low risk. The playground demonstrates the coordination pattern; it is not proof that a real customer support API has been built and validated in a production environment. What I find useful is the visibility. I can see which specialist acted, where approval happened, and how work progressed through the AI Software Factory. The Guardrails I Want Before Giving Agents More Authority The factory floor is interesting, but I pay just as much attention to its guardrails. A workflow can look beautifully organized and still be unsafe if its permissions and release conditions are too loose. The playground’s AI Software Factory includes a concrete set of controls: Least privilege access to toolsNo secrets committed to codeDependency and license scanningStatic application security testing and injection-related checksRequired tests before releaseHuman approval for productionAn audit trail for every agent actionRollback support and post-deployment verification I do not think of these as decorations around the workflow. They determine what an agent may do, what evidence is required, and when work must stop. Least privilege limits tool access. Secret and dependency checks constrain what can enter the codebase. Audit trails help explain actions later. Production approval keeps release authority with a human, while rollback and verification extend safety beyond the initial deployment. For an AI Software Factory to be useful, these controls need to participate in execution, not just appear in a checklist. I want the orchestrator to enforce them consistently across stages. That is also why centralized service context matters. The factory needs to know the service owner, its policies, and the expected incident response before it can route work responsibly. How I Would Start Without Automating Everything on Day One My instinct as a developer is to connect the entire pipeline immediately. Planning agents, coding agents, deployment agents, monitoring agents: the possibilities are exciting. But I would resist that instinct when introducing an AI Software Factory to a team. I would begin with one small, reliable path: requirements, coding, CI, and a human review gate. The initial workflow should stop there. Before adding deployment authority, I want confidence that the inputs are clear, the checks block failures, and the approval boundary behaves as expected. Only after that loop is stable would I expand into deployment and monitoring orchestration. The point is not to have the most agents on day one. It is to establish a trustworthy handoff and then extend it. This changes how I think about the developer’s role. I am not just writing implementation details. I am defining system rules, approval criteria, service context, and the structure through which automated work moves. That is what excites me most about an AI Software Factory. The goal is not to remove engineering judgment. It is to free more of my time for that judgment by coordinating repetitive work around it. I want a factory that ships reliable software, explains its actions, and keeps meaningful decisions accountable to people. Faster code generation is useful. A governed delivery system is the bigger opportunity.
The majority of retrieval-augmented generation (RAG) examples start as follows: document segmentation; create embedding representations for segmented document sections ("chunks"); store those representations in a vector database and use them to "retrieve" the "best matching" document section(s) for any user-inputted search query. That is a good starting point. However, there is one significant limitation to the process described above: not all questions relate solely to similarity. Some questions relate to relationships. For example: Which team owns the API that Checkout Service uses? While a vector search system could potentially identify documents related to "Checkout Service," "Payment API," and "Platform Team," the critical piece of information is the relationship between these concepts: Markdown Checkout Service --DEPENDS ON--> Payment API Platform Team --OWNS--> Payment API This is when graph retrieval becomes a value-added element. Unlike retrieving only documents based on similarity to a query, a graph retrieval layer can retrieve connected Facts from a graph, providing relationship-aware context to a large language model (LLM) while allowing the LLM to generate the final answer. In other words, instead of simply providing additional context to an LLM in terms of a specific set of retrieved documents, a graph retrieval layer would be able to provide structured context. In this tutorial, we will develop a basic graph retrieval layer to enhance a RAG pipeline utilizing Python and NetworkX. We will load relationship triples from a JSON File, build a directed graph, retrieve the local neighborhood of any entity matched by the retrieval layer, and convert that graph-based context into a format suitable for an LLM Prompt. Why Graph Retrieval Helps Most traditional RAG methods are effective for questions that have answers composed within a couple of data "chunks." Examples include: What database does Payment API utilize? As an example, if you have documentation that states, "The Payment API utilizes PostgreSQL," then a vector search should normally identify it. However, as soon as you are looking for information about related facts (i.e., multiple connected pieces of fact), plain similarity search may not provide sufficient results: Who owns the API that the Checkout Service relies upon? In order to determine who owns the API that the Checkout Service relies upon, you need to perform at least two link traversals: Checkout Service -> Payment APIPlatform Team -> Payment API Since this creates a relationship map (a graph), systems, teams, APIs, and databases all represent nodes in the graph, while their relationships all represent the edges in the graph. As long as this structure is in place, retrieval can follow edges (relationships) rather than simply rely on semantic similarities. This does not mean that graph retrieval replaces vector search completely. A hybrid approach has been found to be more successful in most production environments; specifically, the vector search identifies relevant text, while the graph retrieval identifies relevant relationships among those texts, and ultimately the final answer will be determined using both. Therefore, our main emphasis in this article will be solely on the graph retrieval layer. What We Are Building We are creating a short Python application: Loading data (relationship triples) from file "triples.json".Building a directional graph using NetworkX.Identifying all entities mentioned within the user's input query.Retrieving related graph information.Converting that related information to form context for the LLM prompt.Writing the processed contextual information to "graph_context.json." Output will appear as follows: JSON { "question": "which team is responsible for owning the api Checkout Service depends on?", "context": [ "Checkout Service depends_on payment api.", "Platform Team OWNS Payment API." ] } Then you could pass that created contextual information into an LLM prompt portion of a RAG prompt. Project Setup Create a new project folder: Shell mkdir graph-retrieval-rag cd graph-retrieval-rag Create a requirements.txt file: Plain Text networkx==3.3 Install the dependency: Shell pip install -r requirements.txt Create a file named 'triples.json': JSON [ { "subject": "Checkout Service", "relation": "DEPENDS_ON", "object": "Payment API", "source_text": "Checkout Service depends on Payment API during payment authorization." }, { "subject": "Payment API", "relation": "USES", "object": "PostgreSQL", "source_text": "Payment API uses PostgreSQL for transaction metadata." }, { "subject": "Platform Team", "relation": "OWNS", "object": "Payment API", "source_text": "Platform Team owns Payment API." }, { "subject": "Recommendation Service", "relation": "CALLS", "object": "Catalog API", "source_text": "Recommendation Service calls Catalog API to retrieve product details." }, { "subject": "Catalog API", "relation": "USES", "object": "Elasticsearch", "source_text": "Catalog API uses Elasticsearch for product search." }, { "subject": "Search Team", "relation": "OWNS", "object": "Catalog API", "source_text": "Search Team owns Catalog API." } ] This file is intentionally small. In a real system, these triples could come from entity extraction, service catalogs, architecture documents, source code metadata, or cloud inventory. Step 1: Load Relationship Triples Create a file named graph_retriever.py. Python import json def load_triples(path): with open(path, "r", encoding="utf-8") as file: return json.load(file) Each triple has four fields: Plain Text subject relation object source_text The source_text field matters because graph context should remain traceable. When the model uses a retrieved relationship, the system should know where that relationship came from. Step 2: Build a Directed Graph Next, we will create a graph from these triples by importing the NetworkX library for Python, which can create different graph types (for example, directed or undirected). Python import networkx as nx def build_graph(triples): graph = nx.DiGraph() for triple in triples: subject = triple["subject"] object_ = triple["object"] relation = triple["relation"] graph.add_node(subject) graph.add_node(object_) graph.add_edge( subject, object_, relation=relation, source_text=triple["source_text"], ) return graph A directed graph is important because relationship direction changes meaning. This: Plain Text Checkout Service --DEPENDS_ON--> Payment API does not mean the same thing as: Plain Text Payment API --DEPENDS_ON--> Checkout Service Direction matters for dependency analysis, ownership lookup, impact analysis, and many GraphRAG workflows. Step 3: Find Query Entities We're going to find entities mentioned in a question using simple string searching as the means of finding them. Python def find_query_entities(graph, question): question_lower = question.lower() matches = [] for node in graph.nodes: if node.lower() in question_lower: matches.append(node) return matches The code here does not represent a full NLP solution. This is simply a straightforward baseline. In production, you would probably want to do things like aliasing, entity linking, fuzzy matching, etc., or train your own model. In order to normalize the way that a question is phrased versus how something is named in the graph. For instance, "checkout" might be used to ask about the "Checkout Service. Step 4: Retrieve a Graph Neighborhood After identifying the graph element that will answer a question, identify all other elements connected to it. One method to do this would be to gather together both outgoing and incoming edges at each identified node. This could be done with the following code snippet: Python def retrieve_neighborhood(graph, seed_entities, max_hops=2): visited_nodes = set(seed_entities) frontier = set(seed_entities) retrieved_edges = [] for _ in range(max_hops): next_frontier = set() for node in frontier: for neighbor in graph.successors(node): edge_data = graph.get_edge_data(node, neighbor) retrieved_edges.append((node, edge_data["relation"], neighbor, edge_data)) next_frontier.add(neighbor) for neighbor in graph.predecessors(node): edge_data = graph.get_edge_data(neighbor, node) retrieved_edges.append((neighbor, edge_data["relation"], node, edge_data)) next_frontier.add(neighbor) frontier = next_frontier - visited_nodes visited_nodes.update(next_frontier) return deduplicate_edges(retrieved_edges) # Adding a helper function to remove duplicate edges: def deduplicate_edges(edges): seen = set() unique_edges = [] for source, relation, target, edge_data in edges: key = (source, relation, target) if key not in seen: seen.add(key) unique_edges.append((source, relation, target, edge_data)) return unique_edges The max_hops parameter controls how far retrieval travels from the original query entity. For example: Plain Text max_hops=1 retrieves immediate neighbors. max_hops=2 retrieves neighbors of neighbors. While higher values give you a larger amount of additional knowledge about your subject matter, this may also introduce a lot of "noise" into your results. Step 5: Convert Graph Results Into LLM Context The retrieved graph edges are structured data. Before sending them to an LLM, convert them into short, readable facts. Python def format_edges_as_context(edges): context = [] for source, relation, target, edge_data in edges: context.append( { "fact": f"{source} {relation} {target}.", "source_text": edge_data["source_text"], } ) return context This gives the prompt two useful forms of evidence: A normalized graph fact.The original source sentence. That makes the final answer easier to debug and easier to cite. Step 6: Build a RAG Prompt Now create a simple prompt builder. Python def build_prompt(question, graph_context): context_lines = [] for item in graph_context: context_lines.append(f"- {item['fact']} Source: {item['source_text']}") context_text = "\n".join(context_lines) return f""" You are answering a question using graph-retrieved context. Use only the facts provided in the context. If the context does not contain enough information, say so. Question: {question} Context: {context_text} Answer: """.strip() This prompt is intentionally restrictive. The model should use the source instead of guessing. A good production application would also include a format for citations, rules for how to write responses, and fallback behavior. Complete Example Here is the full code: Python import json import networkx as nx def load_triples(path): with open(path, "r", encoding="utf-8") as file: return json.load(file) def build_graph(triples): graph = nx.DiGraph() for triple in triples: subject = triple["subject"] object_ = triple["object"] relation = triple["relation"] graph.add_node(subject) graph.add_node(object_) graph.add_edge( subject, object_, relation=relation, source_text=triple["source_text"], ) return graph def find_query_entities(graph, question): question_lower = question.lower() matches = [] for node in graph.nodes: if node.lower() in question_lower: matches.append(node) return matches def retrieve_neighborhood(graph, seed_entities, max_hops=2): visited_nodes = set(seed_entities) frontier = set(seed_entities) retrieved_edges = [] for _ in range(max_hops): next_frontier = set() for node in frontier: for neighbor in graph.successors(node): edge_data = graph.get_edge_data(node, neighbor) retrieved_edges.append((node, edge_data["relation"], neighbor, edge_data)) next_frontier.add(neighbor) for neighbor in graph.predecessors(node): edge_data = graph.get_edge_data(neighbor, node) retrieved_edges.append((neighbor, edge_data["relation"], node, edge_data)) next_frontier.add(neighbor) frontier = next_frontier - visited_nodes visited_nodes.update(next_frontier) return deduplicate_edges(retrieved_edges) def deduplicate_edges(edges): seen = set() unique_edges = [] for source, relation, target, edge_data in edges: key = (source, relation, target) if key not in seen: seen.add(key) unique_edges.append((source, relation, target, edge_data)) return unique_edges def format_edges_as_context(edges): context = [] for source, relation, target, edge_data in edges: context.append( { "fact": f"{source} {relation} {target}.", "source_text": edge_data["source_text"], } ) return context def build_prompt(question, graph_context): context_lines = [] for item in graph_context: context_lines.append(f"- {item['fact']} Source: {item['source_text']}") context_text = "\n".join(context_lines) return f""" You are answering a question using graph-retrieved context. Use only the facts provided in the context. If the context does not contain enough information, say so. Question: {question} Context: {context_text} Answer: """.strip() def write_json(path, data): with open(path, "w", encoding="utf-8") as file: json.dump(data, file, indent=2) if __name__ == "__main__": question = "Which team owns the API that Checkout Service depends on?" triples = load_triples("triples.json") graph = build_graph(triples) seed_entities = find_query_entities(graph, question) if not seed_entities: print("No matching graph entities found in the question.") raise SystemExit(0) retrieved_edges = retrieve_neighborhood(graph, seed_entities, max_hops=2) graph_context = format_edges_as_context(retrieved_edges) prompt = build_prompt(question, graph_context) result = { "question": question, "seed_entities": seed_entities, "graph_context": graph_context, "prompt": prompt, } write_json("graph_context.json", result) print("Seed entities:") print(seed_entities) print("\nGraph context:") for item in graph_context: print("-", item["fact"]) print("\nPrompt:") print(prompt) Run it: Python python graph_retriever.py Expected output: Python Seed entities: ['Checkout Service'] Graph context: - Checkout Service DEPENDS_ON Payment API. - Payment API USES PostgreSQL. - Platform Team OWNS Payment API. Prompt: You are answering a question using graph-retrieved context. Use only the facts provided in the context. If the context does not contain enough information, say so. Question: Which team owns the API that Checkout Service depends on? Context: - Checkout Service DEPENDS_ON Payment API. Source: Checkout Service depends on Payment API during payment authorization. - Payment API USES PostgreSQL. Source: Payment API uses PostgreSQL for transaction metadata. - Platform Team OWNS Payment API. Source: Platform Team owns Payment API. Answer: The answer is now straightforward: Plain Text Platform Team owns Payment API, which Checkout Service depends on. The important part is not that an LLM can phrase the answer. The important part is that retrieval found the connected facts needed to support it. What This Adds to a RAG Pipeline A standard RAG pipeline often looks like this: Markdown Documents | Chunking | Embeddings | Vector Search | LLM A graph-enhanced pipeline adds another retrieval path: Markdown Question | Query entity detection | Graph neighborhood retrieval | Graph context formatting | LLM In a hybrid system, both paths can work together: Markdown Question | |---- Vector search -> relevant text chunks | |---- Graph search -> connected facts | Combined context | LLM This is useful because vector search and graph retrieval solve different problems. Vector search is good at finding semantically similar text. Graph retrieval is good at following explicit relationships. Production Considerations The graph retrieval layer used in this example is very rudimentary. A production-quality implementation will have many additional "guardrails." Normalized entities are necessary for performing entity matching. Exact string matches will miss most common aliases (i.e., checkout, checkout-service, etc.); however, production-quality implementations will use canonical IDs/aliases/entity linking. Graph retrieval has limits. While there is no limit to how large a graph can grow in terms of returned context, returning too much context can be detrimental. To limit the amount of context returned, implement boundaries, including but not limited to hop count, edge type, node type, confidence value, and source data freshness. All relationships in the graph are not equal in reliability. For example, a dependency established by a service catalog entry may be a more reliable relationship than a dependency inferred from an older document. Therefore, store your confidence level, timestamp, and other source metadata values along with every edge. Not all relationships are equally reliable. Contextual information, in addition to just what was retrieved from the graph, should also contain evidence that supports or refutes the answer. As a result of providing evidence with contextual information, when someone reviews your answer, they will be able to easily verify the answer, and if something does go wrong during development, it will make it easier to debug. Hybrid approaches are best suited for using graph retrieval. While graph retrieval can help the model understand why certain pieces of information relate to each other, document chunks can provide much more detail about those related pieces. When retrieving both types of information, the model will likely receive more complete contextual information. Evaluation is mandatory. You will need to create realistic test questions and determine if the sub-graph retrieved from the database includes enough factual information for answering those test questions. Never assume that graph retrieval will improve performance unless you measure it. Key Takeaways Graph retrieval adds relational contextual knowledge to a RAG framework. A simple directed graph can answer many complex questions involving multi-step logic that would be difficult to accomplish with plain similarity-based search. One key design decision in developing an effective graph-retrieval system is what determines the success of the retrieval layer: does it identify the correct entities and their associated relationships? Graph retrieval works well when the question involves dependency, ownership, impact assessment, lineage, and/or multi-step reasoning. In addition to graph retrieval, build a production-quality retrieval system that includes source tracking, entity normalization, confidence scoring, and evaluation. Try It Yourself Add these triples to triples.json JSON { "subject": "Billing Worker", "relation": "PUBLISHES_TO", "object": "Kafka", "source_text": "Billing Worker publishes payment events to Kafka." }, { "subject": "Data Platform Team", "relation": "OWNS", "object": "Kafka", "source_text": "Data Platform Team owns Kafka." } Then change the question to: Plain Text Which team owns the system that Billing Worker publishes events to? Your goal is to retrieve: Plain Text Billing Worker PUBLISHES_TO Kafka. Data Platform Team OWNS Kafka. Once that works, try lowering max_hops from 2 to 1 and compare the retrieved context. This is a simple way to see why hop count matters in graph retrieval.
Need a break from reading and want to check out some video content? This episode of The Neuron AI Explained is worth watching! Hosts Corey and Grant take a closer look at GPT-6 Astra and Google's Gemini 3.8 Flash, sharing their thoughts on how these models perform beyond the benchmark scores. Sourced from The Neuron AI Explained Youtube Page If you enjoy the video and want to keep learning, check out The Neuron Academy. You'll find hands-on lessons, structured learning paths, and practical examples to help you build on what you already know about AI. Whether you're looking to improve your prompting skills or get more experience with AI agents and workflows, there's plenty to explore. Well, that's enough from me! Happy watching.
When I work with Claude or Codex, I often discuss software architecture with them. I’ve noticed a recurring pattern: both are quick to suggest designs that are more complex than the problem currently requires. The proposals are more general, more extensible, and more “future-proof.” There’s something funny about that last word. The models don’t know what the future of my software will look like. They’re applying familiar engineering advice: anticipate change, make components reusable, leave room to extend the design. Sometimes that’s right. Often, it means building things I haven’t asked for and may never need. What Is the YAGNI Principle in Software Engineering? In those moments, my job is to cut off the extra features. Software engineering has a name for that instinct: YAGNI — “You Aren’t Gonna Need It.” Taken literally, YAGNI sounds like a claim about the future: this feature will never be needed. But that’s stronger than what we can usually know. In practice, it means something more modest: we probably don’t need this now. If we discover that we need it later, we’ll deal with it then. We’ll cross that river when we get to it — and build a bridge when there’s a reason to cross. But why not build the bridge ahead of time? Imagine building a road toward a river, then discovering that you need to cross it. If you already built the bridge, the road may connect to it neatly. You avoid stopping to redesign the approach or rebuild part of the road. Building ahead can make later work easier and keep the pieces compatible. The trouble is that the bridge has a cost before it provides any value. Someone has to build it. Someone has to drag it through the desert to the river. In software, that means writing the code, fitting it into the design, testing it, explaining it, and maintaining it as the project changes around it. The bridge might save us work later, but carrying it there is work now. How AI Coding Tools Change the Cost of Building Software For most of software’s history, that calculation was shaped by the cost of human programming. Designing and implementing extra capability took time. So did reviewing and maintaining it. A feature that might be useful someday had to justify the present cost of building it. Often it couldn’t. YAGNI was a practical defense against paying that cost too early. AI coding tools change part of the calculation. They can make it much cheaper to produce code. A generalized interface, an extra implementation, or a future extension point may take far less time to generate than it once did. If building the bridge becomes cheap, perhaps it makes sense to build it early. The Hidden Costs of AI-Generated Code But “cheaper to write” does not mean “free to own.” Generated code still has to fit the actual design. It can introduce more concepts, more paths through the system, more tests, and more behavior that a developer must understand. It can make the current problem harder to see. And if the imagined future never arrives, the project still carries the bridge. That leaves us with a question, not a new rule: when AI reduces the cost of building ahead, how much should that change our understanding of YAGNI? We shouldn’t answer using only the instinct we developed when every line of code was expensive to write. But we also shouldn’t assume that cheap generation makes speculative features harmless. The useful question is not simply, “Could this be useful later?” Almost anything could. It is: “Is the likely future benefit worth the cost of adding and maintaining this now?” That cost has changed. Our judgment should change with it.
Architecture Review Boards (ARBs) have traditionally evaluated application architectures against key enterprise criteria such as security, scalability, integration, resilience, supportability, and compliance. With the rapid adoption of artificial intelligence (AI), machine learning (ML), and generative AI technologies, organizations are increasingly deploying intelligent solutions that introduce new architectural, operational, ethical, and regulatory challenges. As a result, ARBs must expand beyond traditional review dimensions to assess AI-specific considerations, including data governance, model lifecycle management, explainability, bias mitigation, AI security, operational monitoring, and responsible AI practices. The evolution of ARBs is essential to ensure AI solutions deliver business value while maintaining trust, compliance, accountability, and enterprise risk controls. The objectives of an ARB for AI-based solutions are to: Enable responsible AI innovationManage business, operational, and regulatory risksProtect enterprise and customer dataEstablish governance and accountabilityImprove the success rate of AI initiativesEnsure compliance with organizational and regulatory requirements The table below highlights the key differences between a traditional Architecture Review Board and an AI-focused Architecture Review Board. areatraditional arbAI Solutions ARB Focus Area Application architecture quality, stability, and alignment with enterprise standards. Governance of AI solutions while ensuring business value and risk management. Review Architecture Components Applications, integrations, databases, infrastructure, APIs, and middleware. AI models, LLMs, prompts, vector databases, AI agents, training data, MLOps / LLMOps platforms, and AI services. Security Network security, application security, IAM, encryption, and vulnerability management. Traditional security + prompt injection protection, model security, adversarial attacks, AI supply chain security, and data leakage prevention. Data Governance Data quality, ownership, retention, and regulatory compliance. Data lineage, training data quality, AI data usage rights, consent management, data sovereignty, and model input/output governance. Compliance Industry standards, regulatory requirements, and enterprise policies. AI regulations, ethical AI principles, transparency requirements, and responsible AI frameworks. Risk Operational, technical, and cybersecurity risks. Hallucinations, bias, misinformation, model drift, ethical risks, and reputational risks. Explainability Not a major review criterion. Critical requirement to ensure AI decisions and outputs can be understood, justified, and audited. Bias and Fairness Outside review scope. Bias detection, fairness controls, and mitigation mechanisms. Testing & Validation Functional, performance, integration, security, and UAT testing. Prompt testing, adversarial testing, hallucination assessment, and AI output validation. Operations & Monitoring Application monitoring, logging, incident management, and SLAs. Performance, drift detection, output quality, token consumption, and AI safety monitoring. Lifecycle Management Software development lifecycle (SDLC), release management, and application support. Model lifecycle management, retraining strategy, model versioning, LLM updates, and MLOps/LLMOps governance. Accountability Application owner and business sponsor accountability. Accountability for AI outcomes, model ownership, risk ownership, and human-in-the-loop oversight. Decision Criteria Security, scalability, resilience, integration, supportability, and compliance. Explainability, trustworthiness, fairness, governance, responsible AI, and business risk controls. Success Measures System reliability, performance, availability, and compliance. Business value realization, responsible AI adoption, model accuracy, user trust, regulatory adherence, and risk reduction. Prompt Governance Not Applicable Prompt design, validation, security, and lifecycle management Model Selection Not Applicable Evaluation of model suitability, cost, accuracy, and risk Human Oversight Limited Human-in-the-loop review and approval processes AI Ethics Rarely Reviewed Fairness, transparency, accountability, and societal impact Vendor Lock-In Infrastructure focused AI provider dependency and model portability Cost Governance Infrastructure and licensing Token consumption, inference cost, and model hosting costs Responsible AI Limited Mandatory governance and compliance requirements The shift in ARB assessment perspectives can be summarized through the following key questions: Below is a six-pillar AI ARB framework for solution reviews and assessments. Business value assessment: Organizations deploy AI because it is technologically attractive rather than business-driven. The ARB team evaluates revenue growth, cost optimization, productivity improvement, customer experience enhancement, and decision-making effectiveness. Data governance and privacy: Data is the most critical asset in any GenAI solution. Poor data governance can expose sensitive information and create significant compliance risks. The ARB team evaluates data classification, data protection, and regulatory compliance.Security architecture review: GenAI systems introduce new attack vectors not commonly found in traditional enterprise applications. The ARB team evaluation areas include identity management integration, role-based access control, API gateway protection, encryption at rest and in transit, network isolation, key management, and security monitoring.Responsible AI governance: Responsible AI should be a mandatory review category within every GenAI ARB process. The objective is to ensure AI systems are fair, transparent, accountable, and trustworthy. The ARB team evaluates fairness, transparency, accountability, and explainability. Architecture and integration assessment: The ARB team evaluation areas on solution architecture, integration strategy, RAG architecture, and multi-model strategy.Operations, monitoring, and FinOps: GenAI projects succeed technically but struggle operationally after deployment. The ARB team evaluates business, technical, and financial metrics. Below are the best practices for enterprise ARBs reviewing GenAI solutions: Establish a dedicated AI review track within the ARB.Mandate Responsible AI assessments.Require data classification and privacy reviews.Standardize AI architecture reference patterns.Define AI monitoring and observability standards.Include Legal, Security, Data Governance, and EA stakeholders.Adopt a FinOps approach for AI cost governance.Establish a continuous AI governance process rather than a one-time approval activity. Conclusion Future ARBs are no longer responsible solely for evaluating system architecture. The review board must become a multidisciplinary governance body capable of balancing innovation, risk, compliance, and ethics. Organizations that evolve their ARB practices to address generative AI-specific concerns will be better positioned to scale AI adoption while maintaining trust, transparency, and regulatory compliance.
Key Takeaways Role-based access control (RBAC) and content-tagging systems check whether a requester's credentials match a label attached to data. That check has nothing to say about a derived, cached result — a plain number with no tag of its own.A cached metric like churn_rate = 0.114 can be computed from a query that touches a restricted column (income) and then be served to a department that was never allowed to see that column, without a single existing access control catching it.The fix is to gate retrieval on the result's derivation graph — the tables, columns, and filters that produced it — rather than on a tag attached after the fact.In benchmark testing, this reduced a structural cross-department leak rate of 18.8%–25.5% to zero, at a real, measurable cost: roughly 13 additional query executions per 100 requests, and a gate-check predicate costing 0.09 microseconds.The mechanism does not stop inference attacks, a compromised memory store, or collusion — it closes one specific, previously unguarded gap in agent-memory retrieval. A Clean Integer That Still Leaks a Restricted Column Take a concrete scenario. A Finance agent runs a query that joins a transactions table against a customer_pii table — which includes an income column — to compute a churn_rate for customers who have gone quiet in the last 90 days. It gets back a single float: 0.114. Nothing about that number looks sensitive. No names, no account numbers, no raw income figures. The agent caches the result in shared memory so the next agent that asks for churn_rate does not have to recompute it. A week later, a Marketing agent asks the same shared memory for churn_rate and gets 0.114 back instantly, with no query executed. Marketing was never granted access to income. Its role-based access-control (RBAC) entry explicitly blocks that column. But nothing in this transaction touched income directly — Marketing did not query the column, did not see a row containing it, and did not request anything with "income" in the name. It asked for a key performance indicator (KPI) by name and got a float back. By any access-control system running in production today, that transaction is clean. And it is a policy violation: the number 0.114 was derived from a computation Marketing was never authorized to run. This is the finding at the center of a paper co-authored with Sudhir Vissa, "Lineage-Aware Memory Governance: A Derivation-Gated Framework for Privacy-Preserving Column-Level Access Control in Enterprise AI Agents," accepted at IEEE Access (DOI: 10.1109/ACCESS.2026.3730363). This article walks through the engineering mechanics of the failure and the fix, using the worked example and architecture diagram from the paper. The Access Check Every System Runs — and the One It Doesn't Strip away the vendor language, and every access-control mechanism guarding a piece of data — RBAC, attribute-based access control (ABAC), content tagging, ownership metadata — runs some version of the same predicate at retrieval time: Shell allow(requester, object) := tag(object) ⊆ permissions(requester) The object carries a label — a sensitivity classification, an owner, a role requirement — and the check asks whether the requester holds a credential matching that label. Apache Ranger and Databricks Unity Catalog enforce this at the column level for raw queries: they intercept a SELECT statement and check whether the requesting principal is allowed to read the specific columns named in it. That works well for exactly the case it was built for: stopping an unauthorized read at the point of query execution. Shared agent-memory systems — MemGPT, Zep, A-MEM, and the newer governed-memory architectures being built for enterprise deployments — extend the same pattern to cached results. A memory entry gets an owner, maybe a sensitivity tag, maybe a role requirement, and retrieval is gated on whether the requester's credentials match. This is a reasonable design, and it is also where every one of these systems stops. The problem is that churn_rate = 0.114 has no tag to check. It is a scalar. Nobody attached a sensitivity classification to it, because nothing about the value is sensitive — a churn rate cannot be reverse-engineered into an income figure. The column-level access-control list (ACL) at the database layer did its job perfectly: it verified that Finance was allowed to touch income when it ran the join. But that check fired once, at write time, for the agent that computed the number. It has nothing left to say about the agent that retrieves the cached result afterward. By the time 0.114 sits in shared memory, the access-control moment has already passed, and the object in front of the second access-control check carries no trace of the columns that produced it. So the predicate every current system checks — does the requester's tag match the object's tag — answers the wrong question for this failure mode. The question that actually determines safety is: Shell safe(requester, result) := columns_touched(result.derivation) ⊆ permissions(requester) That is not a check on the object. It is a check on the object's derivation — the tables it joined, the columns it read from each of them, and the filter predicates that shaped it. No system in the current agent-memory landscape records that, which means none of them can evaluate it. A Worked Example: How Finance's Churn Rate Leaks to Marketing Here is the derivation graph from the paper — Figure 1 — showing exactly what has to be tracked to make that second check possible. Read it left to right. Three source tables feed a join: transactions, customers (with customer_id and signup_date), and customer_pii (with last_txn_date and income). The join step applies a filter — last_txn_date < now()-90d AND income > 20000 — and produces churn_rate = 0.114, tagged with the producing department and a time-to-live (TTL) epoch for eviction. The part that matters is the dashed box on the right. Two values are computed once, at the moment the result is cached, and stored alongside it. The sensitivity tag, S(a), is the union of every column touched across every step of the derivation, intersected with the organization's registry of sensitive columns: Plain Text S(a) = (∪ᵢ Cᵢ) ∩ SensitiveColumnRegistry For this cached entry, S(a) = {income}. It does not matter that income never appears in the output — the tag is computed from what was read, not from what was returned. The definition hash, H(a), is a fingerprint of exactly how the metric was computed: the sorted table names, the sorted column set, and the filter predicate, hashed and truncated to 12 characters: Plain Text H(a) = SHA256(sort(tables) || sort(∪ᵢ Cᵢ) || φ)[0:12] This second value is not for access control. It catches a different, related failure: two departments computing a metric with the same name through different logic — a 90-day churn window versus a 60-day window, say. If two cached entries share a metric name but their hashes differ, that is a silent definition conflict, and it can be surfaced automatically instead of showing up as a mismatch in a board deck. It comes along for free once derivation is already being recorded for the access-control reason. Both values are sub-microsecond to compute. The retrieval-time check is then a single set-difference: is S(a) a subset of what this requester is permitted to see? For Marketing, whose permission set explicitly excludes income, the answer is no, regardless of how inert the value 0.114 looks. The Fix: Gate Retrieval on Derivation, Not on Tags The mechanism described in the paper is called the Analytical Memory Unit (AMU) — a memory schema that carries the derivation graph as a first-class field, plus a retrieval algorithm that gates on it. Figure 2 shows the full architecture. Two paths run through this diagram, and they solve two different problems. The read path (left and center) is the leak-prevention mechanism. A requesting agent asks for a metric by name. The lineage gate pulls every AMU ever stored under that name, resolves the requester's permission set once, and scans candidates most-recent-first — a deliberate policy choice, so that when a safe candidate exists, the department gets the freshest one rather than an arbitrary historical value. For each candidate, the gate checks a single predicate: is the cached S(a) a subset of P(department)? The first candidate to pass gets served, and a memory-reuse counter increments. If a candidate fails — Marketing hitting the Finance-computed churn_rate — it is skipped, and the loop moves to the next-oldest candidate. If nothing in the store passes, the agent falls back to a fresh, in-scope computation of its own, which is then written back into the store through the same path, available to the next requester who is actually permitted to see it. The write path (right) is unrelated to access control — it is the definition-conflict detector. Every new AMU is compared against existing entries under the same metric name; if a cross-department pair has matching metric names but different definition hashes, that is flagged for downstream review. It never blocks the write. It simply surfaces a signal that two teams' business logic has silently diverged. The formal safety guarantee behind the read path is a straightforward case analysis: the retrieval algorithm has exactly two exit points, a memory-served return and a fallback return, and the proof shows neither path can hand a requester a result whose derivation touches a column outside their permission set — provided the lineage record is complete. That qualifier does real work, and it is worth sitting with before treating this as a drop-in fix. What It Costs, Measured None of this is useful if it is a paper mechanism that falls apart under load or eats the redundant computation that shared memory exists to avoid in the first place. Six experiments in the paper attempt to break it. Across a synthetic five-table schema and a denser eight-table TPC-H benchmark schema, naive content-gated memory — the pattern every current system uses — leaked cross-department results at 18.8% and 25.5% of retrievals, respectively (30 seeds each, effect size around d≈7–8, well past the conventional threshold for a large effect). Lineage-gated retrieval brought that to zero in both configurations. To be precise about what that number means: this is the formal safety guarantee holding in the tested setting, not an empirical discovery on its own. The empirical finding is the naive baseline's leak rate; the zero is what the proof predicts. That protection is not free. Gating out unsafe candidates means more fallbacks to fresh computation: the reuse rate dropped from 95.8% under naive caching to 81.5%–82.6% under lineage gating, roughly 13 additional query executions per 100 requests. That cost shows up as extra compute, not as gating latency — the permission-check predicate itself runs at 0.09 microseconds, and even the worst-case retrieval scan, with every candidate blocked across a store of 50, tops out at 13.82 microseconds. In a realistic production store, where a metric accumulates at most a handful of department-variant entries, that is sub-2-microsecond in practice, not a meaningful line item next to a query that takes milliseconds to seconds. Two further results matter for anyone deciding whether to trust this in production. First, a completeness-degradation experiment: the safety proof assumes lineage recording is complete, but real instrumentation is not always. Testing with deliberately truncated lineage — simulating buggy instrumentation or agents that under-report what they touched — showed the protection degrading gracefully rather than falling off a cliff, converging back to zero leakage by 75%–90% completeness, and degrading faster specifically on schemas where sensitive columns sit behind more joins. That is a useful operational signal: instrument the deeply nested joins first. Second, and more important for anyone concerned this only works when the agent cooperates: a real-agent test wired lineage extraction directly into the database driver layer, using a Structured Query Language (SQL) parser to read the actual statements a LangChain agent executed, with no self-reporting from the agent required. Across nine round-trips against a real database, there were zero cross-department leaks, and two genuine definition conflicts were caught automatically. The cleanest integration point turns out to be exactly where you would want it: wrap the cursor, parse every executed statement, and the agent never has to know it is being watched. What This Doesn't Fix The credibility of a mechanism like this depends on being precise about its edges, so three limitations are worth stating plainly rather than leaving implicit. It does not stop inference attacks: a derived feature that encodes sensitive information without ever naming the source column in a way the lineage extractor can see. A hand-crafted risk score computed from income, where that dependency is not captured in the executed query, will slip past the gate, because the gate can only check what the lineage record actually contains. This is the gap the paper's authors flag as the most important one left open. It assumes lineage recording is honest and complete. Self-reported lineage from a cooperative agent is a weaker foundation than lineage extracted automatically from executed SQL, which is exactly why driver-layer interception matters more than it might first appear: it removes the agent's ability to misreport what it touched, whether deliberately or through a bug. It does not defend against a compromised memory store or an insider with direct infrastructure access, and it does not, on its own, stop a requester from triangulating a blocked column by combining several individually permitted results that are jointly informative about it. Those need their own controls: encryption, audit logging, differential privacy, and infrastructure trust boundaries. This is one layer in a defense-in-depth stack, not a replacement for the source-layer controls it sits alongside. The Question Worth Asking About Your Agent-Memory Stack If you are building or evaluating a shared memory layer for agents, there is one question worth running through concretely: when your retrieval path decides whether to hand a cached result to a requesting agent, what predicate is it actually evaluating? A tag someone attached when the entry was written? A role the requester happens to hold? Or a set-membership check against the actual columns that produced the value? Most systems on the market today, including every system benchmarked in the referenced paper, are checking the first two. RBAC and content tagging are not wrong; they answer a real question, just not the one that determines whether a specific cached number is safe for a specific requester. That is a derivation question, and it needs a derivation record to answer it. The mechanism described here costs microseconds and a few hundred bytes per cache entry. What it buys is a governance layer that can prove, mechanically, at retrieval time, that a result never crossed a column-permission boundary — rather than discovering the leak in a post-incident audit. This article is a plain-language, engineering-focused walkthrough of "Lineage-Aware Memory Governance: A Derivation-Gated Framework for Privacy-Preserving Column-Level Access Control in Enterprise AI Agents," co-authored with Sudhir Vissa (SAGE7 AI), accepted at IEEE Access (DOI: 10.1109/ACCESS.2026.3730363). Figures are reproduced from the published paper. The full derivations, threat model, and experimental protocol are available in the paper and its supplementary material.
Senior Consultant,
Rick Freedman
Agile Coach,
Berlin Product People GmbH
Developer Evangelist,
Port.io
Data and AI