Table of Content
Subscribe to our Newsletter
Get the latest from our team delivered to your inbox
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Ready to get started?
Try It Free
An engineer at a bank asks a coding agent for a small cleanup. The teller service stores each account's status as a single letter, A for active and C for closed, and the team wants readable values instead: ACTIVE, CLOSED, and a new DORMANT. The service is written in Java and saves the status to the ACCOUNT table in Db2. The agent updates the enum, the JDBC insert and the unit tests. The build and the tests pass, and the diff is easy to review.
The bank is made up, but its setup mirrors the software stack at real financial institutions, at a much smaller scale.
The agent knew exactly what it was changing, but it had no way to see what the change did to anything else. A nightly COBOL batch program reads the same column and charges the monthly fee only on accounts marked A. A PySpark job copies the table into the lakehouse every night, and the finance team's dashboard counts closed accounts by filtering on C. None of them throws an error, but the fee charges stop and the closed account count drops to nothing.
All three live outside the repository the agent was working in. Access to every repository wouldn't have fixed that on its own, because the same value goes by different names in different codebases, and following it from one to the next by search is slow and unreliable. That's the problem context engineering has to solve once a codebase grows past one team. The agent has to see what depends on the code it changes, as well as the code itself.
Andrej Karpathy, who helped popularize the term, describes context engineering as "the delicate art and science of filling the context window with just the right information for the next step." For a coding agent, that information comes from two places. One is what you write ahead of time, mainly rules files like CLAUDE.md or AGENTS.md. The other is what the agent finds while it works: the files it reads, the searches it runs and the tools it calls.
The bank's rules file is a good one. It covers how the team works: use the shared money type for amounts, run the integration tests before opening a pull request, never edit the generated database mappers by hand. It even says "check for downstream consumers before changing a column", and the agent followed it. But a rule can only tell the agent to look. The list of consumers lives in other teams' repositories and changes every quarter, so the rule can't say what the agent will find.
So the agent searched, and the search came back clean.
Search misses consumers like these because the two sides of a dependency are written differently. In this change, each one is hidden in a different way.
A language server doesn't help here either. It resolves symbols inside one workspace and one language, and a Java class and a COBOL program that share a Db2 column share no symbol, because their link exists only in the data. The same is true when a TypeScript service reads a table that a Python job writes, or when two Java services in different repos share a queue.
We tested this on a codebase with the same shape as the bank's: IBM's public CICS Banking Sample Application, split into four repositories. COBOL programs with JCL and Db2 sit on one side, Java services on the other, and they share Db2 tables and nothing else. Every setup used the same model, harness, prompt and turn budget. Only the context changed: local repo access, local repo plus a language server, or local repo plus Foundational Context of Code and Data over MCP.
ACCOUNT table before a schema change? Every setup answered, but without the graph the agent listed more code that doesn't touch the table. The stronger model did worse than the cheaper one, both in our benchmark and when we tested with real Fortune 100 enterprises. It searched harder and found more candidates, but had no way to check them.We ran the same comparison with agents from other vendors and saw similar results. So the difference came from the context the agent had, not the model. The full benchmark covers the method and the results.
What the bank's agent needed wasn't a smarter model. It was a map of what depends on what.
Foundational Context of Code and Data builds that map by analyzing source code across repositories and languages. It resolves the cases search can't, including JCL dataset names built at run time and table names injected from config. It also connects each table and column to every downstream consumer that reads or writes it, from programs, jobs and services to dashboards, along with their owners. The agent queries it over MCP in the middle of a task. This example uses Java and mainframe code, but the same approach works for code in Python, Scala, TypeScript, Go and other languages.
Run the bank's change again. Before editing, the agent asks what reads or writes ACCOUNT.STATUS. The answer lists the COBOL fee batch, the PySpark extract and the finance dashboard, and who owns each one. Now the agent can propose a safer change: add a new column and leave the old codes in place, or open the pull request with the three owners flagged. The change can still go ahead, but someone has to decide that on purpose.
So the rules file tells the agent when to ask, and the graph answers. The bank's rule needs only a small update:
## Changes other systems may depend on
Before renaming, dropping or changing the type or values of a table, column or dataset:
1. Use the Foundational MCP tools to list everything that reads or writes it, in any repo or language, and who owns it.
2. Summarize that list in the pull request description.
3. If anything outside this repo depends on it, flag it and wait for a human review.
You can also ask these questions directly before a change:
STATUS column of ACCOUNT, across all our repos?"A rule raises the odds that the agent checks first, but it doesn't guarantee it. Karpathy says as much in the same post: context engineering is one small piece of an LLM app, and verification and guardrails are separate work on top of it. So the same question gets asked a second time, at review. Impact analysis on the pull request shows the reviewer every downstream job, service, dashboard and other consumer the change affects, whether a person or an agent wrote it. In the bank's case, that's the point where the fee batch owner sees the change before it merges, not after the first month of missing fees.
That's why Foundational works at both points: it gives the agent context while it codes, and it reviews every code change before merge. Together they let any AI coding tool work autonomously in a complex enterprise stack without the risk of breaking the systems that depend on its changes.
Foundational Context of Code and Data runs as a hosted MCP server and works with the coding agents your engineers already use. Setup takes a few minutes, and the steps for each tool are in our help center.
Start small. Pick one repository where agents already open pull requests that touch shared tables, add the rule above, and turn on impact analysis for its pull requests. After a few weeks, look at how often the agent checked impact before editing and what review still caught.
Want to see how this works on your own code? Book a demo and we'll walk through it with your stack.
It's the practice of deciding what an AI coding agent sees before and during a task: instructions, code, tool results and outside knowledge. For changes that other systems depend on, that includes the impact of the change on code, jobs, dashboards and other consumers outside the repository the agent is working in.
CLAUDE.md or AGENTS.md enough?Rules files are good at telling the agent how your team works. They can't list what depends on a given table, column or dataset, because that lives in other repositories and keeps changing. Use the rules file to tell the agent when to look it up, and an MCP server to give it the answer.
The dbt MCP server gives the agent your dbt project: models, tests and the DAG. A code and data graph also covers the application code, Spark jobs, mainframe programs and BI tools outside the dbt project. Teams that use dbt can run both.
It works with Claude Code, Cursor, OpenAI Codex, GitHub Copilot and Devin, plus other MCP clients listed in our help center.
It analyzes source code in languages including Python, Java, Scala, TypeScript, Go and SQL, mainframe code such as COBOL and JCL, and tools like dbt and Spark. The code can come from GitHub, GitLab, Bitbucket, Azure Repos or any other source.
No. The MCP server only returns what your Foundational account can already see, and it returns lineage and definitions, never table contents. Foundational needs read-only access to your source code, and its warehouse connections read metadata only. Foundational is also SOC 2 Type II certified.
It significantly lowers the risk. The agent sees the impact of a change before it edits, and impact analysis on the pull request catches what still slips through. In our benchmark, and in deployments at Fortune 100 enterprises, we saw a large improvement and a significant reduction in risk. It works alongside your tests and review, not instead of them.
Book a demo and we'll walk through it with your stack.
Book a demo and we'll walk through it with your stack.
Book a demo and we'll walk through it with your stack.