What happens when coding agents can see your entire system
Imagine your coding agents can see every service, database, DNS record, and line of code in your company—and then coordinate with each other while they change it. That’s the world this engineering team stepped into when they built “Architect”, a massive graph of their entire platform, and wired it into a fleet of AI agents.
Working with multiple coding agents at once
Instead of treating AI as a single assistant, the team leans heavily into parallelism. A typical day starts with multiple agents running side by side on dual monitors: one exploring specs, another refining them, others preparing implementations. Once a specification looks good, they trigger “apply” flows that spin up new Git worktrees and start making changes.
This isn’t just one agent doing everything. It’s four to six agents working on related tasks at the same time, each focused on a different step of the workflow. That parallelism is what turns AI from a helper into a real force multiplier: more features, more changes, more experiments in the same amount of time.
Letting agents talk to each other: Atrium
Of course, once you run several agents in parallel on the same codebase, they start stepping on each other’s toes. Files clash, commits conflict, and agents get confused by unexpected changes. To fix this, the team built an internal tool called Atrium.
Atrium acts like a chat and memory hub for agents. When an agent starts work, it registers in Atrium and announces which files it’s touching. Other agents can see that activity, wait if necessary, and then exchange messages like:
“I’ve modified this file; here are my changes.”
“Great, will that conflict with what I’m doing?”
This simple coordination layer means agents can safely work in parallel without constantly overwriting each other. Over time, Atrium evolved from a basic message bus into a lightweight memory system, backed by a graph database, where each piece of work becomes a node with attached “memories” that the next agent can pick up.
Chaining agents into structured workflows
On top of Atrium, some engineers built more structured, multi-step flows. One example uses a tool called Beads, where you define a “formula” for how work should happen:
- Agent A analyzes a problem and proposes a plan.
- Agent B implements the change.
- Agent C reviews the result.
A dispatcher orchestrates these steps, kicking off each agent in turn and publishing handoff data into Atrium. The next agent then starts with full context instead of from scratch. It’s essentially a small, agentic workflow engine, but still light enough to be practical in day-to-day work.
Why graphs unlock a new level of agents
A key idea behind all of this is graph-based data. Instead of storing information in isolated systems or flat tables, the team models everything as nodes and relationships: services calling services, code depending on code, DNS records pointing to infrastructure, and so on.
They experimented with relational databases and recursive SQL, but quickly hit performance walls—100% CPU, bursting instances, and ugly recursive queries. Moving to a graph database (Neo4j) gave them what they needed: fast traversal of complex relationships, easy modeling of connections, and a natural fit for how agents think in terms of “what’s connected to this?”
This graph-first approach also saves tokens. Instead of asking a model to repeatedly parse huge codebases or logs, agents can query the graph for precise relationships and facts. One lookup replaces thousands of tokens of reasoning.
Architect: a unified graph of the entire platform
All of this comes together in Architect, the team’s internal system that unifies their platform into one giant graph. Architect isn’t a single database; it’s a collection of around nine graphs stitched together with composite queries:
- Service graph: Built from tracing data, it shows which web app or job calls which service, database, or queue.
- Code graph: Continuously ingests Git repositories, analyzes modules, classes, and even method-level dependencies, and tracks code changes over time.
- DNS graph: Models DNS chains end-to-end, so you can see how a hostname resolves across multiple hops.
- Data store topology graph: Maps database instances, clusters, and replicas across data centers.
- Data graph: Captures schemas, tables, and fields for structured data stores, plus primary/foreign key relationships.
- Infrastructure graph: Represents physical and virtual infrastructure—machines, racks, floors, and data centers.
- Org graph (in progress): Connects systems and code to the teams that own them.
These graphs are joined via shared fields. For example, a web app node in the service graph connects to a host in the infrastructure graph, which in turn pins it to a specific rack and data center. A web app also links to its artifact, which links to the code module that produced it in the code graph.
The result: you can start from a single API endpoint and trace it all the way from code, to service, to database, to machine, to team ownership—and back again.
Starting with the service graph: the skeleton of reality
Architect didn’t appear fully formed. The team started with one core question: what is actually talking to what in production?
That led to the first major component: the service graph. It ingests traces from all web workloads and extracts only what matters for topology: “this web app called that web app,” “this web app queried that database,” and so on. Everything else gets filtered out.
The service graph became the skeleton of reality: a live picture of how the platform behaves in production, not how the code thinks it behaves. Once that skeleton existed, new questions emerged:
- How is this call implemented? → add the code graph.
- Where is this running? → add the infrastructure graph.
- Who owns this? → add the org graph.
From there, Architect expanded outward, one graph at a time.
Scaling to millions of traces per second
Getting the service graph into production wasn’t smooth. The first attempt used Kafka Connect to stream traces directly into Neo4j. It worked in test and beta, then collapsed spectacularly in production: live traffic peaked at around 7 million spans per second, and Kafka Connect simply gave up.
The fix was to move to Apache Flink, a distributed stream processing engine. With Flink, they could:
- Scale consumers horizontally across many task managers.
- Tune parallelism per pipeline (e.g., heavy for API/database spans, lower for queues).
- Filter and aggregate aggressively so only ~30% of spans become graph records.
Even though they read millions of spans per second, they only write around 4,000 records per second into Neo4j. The pipeline throws away noise, keeps the topology, and keeps up with production load.
To squeeze out more performance, they even disabled Flink checkpointing. Because they’re processing such huge volumes of traces, missing a handful of calls doesn’t matter—those patterns will show up again soon. Instead, they rely on separate extract-and-clean processes plus the code graph to reason about what’s new versus what might be missing.
Connecting code changes to real-world impact
Once the code graph was in place, things got really interesting. Every module, class, and method is mapped, along with which web apps depend on which modules and which flows they’re part of. Architect can now answer questions like:
- “If I change this class, which critical payment flows might I affect?”
- “Is this change touching anything that runs during peak season?”
- “Does this part of the code need higher test coverage than usual?”
This logic is wired into GitLab pipelines. When an engineer opens a merge request, the pipeline calls Architect (via API or MCP) to trace the impact of the change. Today it mostly surfaces FYI-style insights (“you’re touching a critical flow”), but the goal is to enforce dynamic gates: for example, requiring 100% test coverage for ultra-critical paths, or blocking risky changes during a code freeze while still allowing safe, non-critical changes to ship.
From visibility to automated fixes
Visibility is powerful, but the real win is action. The team is building a layer on top of Architect called Sentinel. Sentinel continuously runs rules and reports across the graphs to detect anti-patterns, like:
- Cross-data-center SELECTs hitting a primary database instead of a local replica.
- Services with unhealthy dependency chains or risky latency profiles.
These checks run on a schedule and produce reports for teams: “here are the things you should probably fix.” But the roadmap goes further: each rule can be paired with an auto-fix.
For example, if a rule detects a cross-DC primary SELECT, Architect and the code graph know exactly which query, in which method, in which module, in which repository is responsible. An agent can then:
- Pick up a message from a Kafka stream describing the issue.
- Clone the repo into a Git worktree.
- Apply the fix (e.g., switch to a local replica).
- Open a merge request and assign it to the owning team.
Humans stay in the loop as reviewers, but agents do the grunt work. This is very close to the vision many people have when they talk about building their own agentic operating system for software development.
Designing for agents: frameworks, skills, and guardrails
One of the strongest lessons from this journey is that you need to design your codebase for agents if you want them to be effective. Early on, different agents implemented similar features in different ways. The end result worked, but the code was inconsistent and harder to maintain.
The team responded by introducing strict frameworks and conventions:
- Common Java patterns and base classes for ingest pipelines.
- Factory methods and enums to register new span types or file types.
- Standard hooks into Atrium before most actions (“I’m about to do X, is anyone else doing this?”).
On top of that, they built a skills library for agents: reusable patterns for adding a new span type, a new file type, or a new data source. In some cases, these skills are little more than structured copy-paste templates, but agents are particularly good at filling in the complex parts—like writing efficient Cypher queries.
With frameworks and skills in place, adding a new data source to Architect is now measured in days, not months. Once the plumbing and access are ready, agents can generate most of the ingestion logic in a few hours.
MCP, APIs, and CLI tools: choosing the right interface
Architect exposes its capabilities primarily through two interfaces:
- APIs for structured, deterministic calls (e.g., “given this commit, tell me which flows it touches”).
- MCP tools (Model Context Protocol) for more open-ended, exploratory queries where the agent doesn’t yet know what it needs.
MCP has become the default integration point across the organization: many internal tools plug into Architect via MCP so that any agent-based environment—like a dev environment or a chat interface—can query the graphs naturally.
But there’s a trade-off. Too many MCP tools can cause “tool bloat” and tool storms, where agents bounce between tools, blow up context, and sometimes hallucinate their way down the wrong path. That’s why the team logs tool usage, intent, and user stories, then distills common patterns into more specific tools or even plain APIs. In some cases, a simple CLI tool might be the best interface: easier for agents to call, cheaper in tokens, and less prone to confusion.
When every engineer can see everything
Today, engineers can use coding agents that tap directly into Architect. That means any developer can:
- See how their service is deployed, including the hardware it runs on.
- Inspect DNS chains and latency to shared services like S3.
- Understand which merchants or flows might be impacted by a noisy neighbor on a shared host.
This level of visibility is empowering—but it’s also a new risk. With great observability comes the ability to ask hard questions of other teams (“why is my DNS chain four hops while theirs is two?”) and, more seriously, to infer sensitive information like traffic volumes per merchant or details about vulnerabilities.
To manage this, the team is working on permission models and access controls. Not every user should be able to see everything, especially as Architect starts to ingest vulnerability data, CVEs, or penetration test results. The challenge is to keep the system as open and useful as possible while still limiting what bad actors—or over-curious agents—can do.
Rethinking documentation and knowledge
Most of the data in Architect today is “hard” system data: traces, code, infra, schemas. But the same approach could be applied to softer, human-layer information: documentation, design decisions, incident reports, and more.
Teams already lean on agents to generate and summarize documents in tools like Confluence. Over time, it’s easy to imagine Architect ingesting that content into a knowledge graph, linking it to the actual services and code it describes. Agents could then:
- Generate up-to-date architecture diagrams automatically.
- Produce weekly release notes and design docs from factual graph data.
- Cross-reference incidents with the code and infra that caused them.
This mirrors a broader shift: we’re moving from documentation written for humans and manually read by humans, to documentation written with agents and primarily consumed by agents—who then translate it back into human-readable summaries on demand.
Incident response with agents that know everything
One of the most compelling future use cases is incident response. If an agent has access to Architect’s full graph—services, code, infra, incidents, and ownership—it can:
- Start from a specific symptom (“this endpoint is timing out in DC1”).
- Map all downstream dependencies and recent changes.
- Correlate with metrics and logs from monitoring systems.
- Suggest likely root causes and remediation steps.
For this to work safely, the prompts need to be very specific. “This is on fire; help me fix it” is a good starting point. Vague prompts like “something seems wrong, what is it?” are more likely to send the agent chasing ghosts. Even with a perfect graph, poor prompting and too many tools can still produce bad answers.
That’s why prompt quality and guardrails still matter. Agents are incredibly powerful when you give them precise questions and clear constraints; they’re much less reliable when you ask them to “just go find something.”
How to start building something like this
If you want to build your own version of Architect, the team’s experience suggests a few practical steps:
- Start with the service graph. It’s the skeleton of reality: what is talking to what in production. If you have tracing, you already have the raw data.
- Iterate, don’t over-design. Their first pipeline used Kafka Connect and failed at scale. They switched to Flink, tuned it over weeks, and only later hardened CI/CD and tests.
- Earn buy-in with visible value. They convinced data owners (observability, infra, code platform teams) by showing concrete prototypes and answering questions they couldn’t previously answer.
- Design for agents from day one. Use consistent frameworks, clear patterns, and good documentation so agents can extend the system safely.
- Keep humans in the loop. Especially for auto-fixes and critical flows, treat agents as powerful collaborators, not fully autonomous operators.
From there, you can layer on more graphs, more automation, and more agent workflows—much like you would when you wire multiple agents together in other domains. The difference here is that the agents aren’t just reading files; they’re navigating a live, unified model of your entire system.
The future: agents, graphs, and rethinking how we build systems
We’re still early in this shift. In just a few months, a small team—amplified by agents—built a production-grade, multi-graph view of a large platform and wired it into their development lifecycle. What might have been a year-long bet a few years ago is now a fast, iterative experiment.
The bigger question is what happens when more organizations do the same. If every serious system has an Architect-like graph behind it, and every engineer works through a swarm of specialized agents, we may end up rethinking not just how we code, but how we design tooling, documentation, incident response, and even org structures.
For now, one thing is clear: when coding agents can see your entire system—and talk to each other while they change it—the way we build and run software starts to look very different.
Comments
No comments yet. Be the first to share your thoughts!