05 | Giving AI a Bird's-eye View

When working with AI coding assistants on a large codebase, there's a fundamental issue: the AI can only realistically read a handful of files, but your system might span hundreds or thousands of files across multiple services. The AI sees a slice. Which is most of the time fine, but sometimes you need it to understand the whole system, especially during planning. If you want the AI to help you think through a new feature, but it doesn't know what APIs already exist, what tables are in your database, or how your services communicate. It's like asking someone to design a room addition when they've never seen the floor plan. I've been using [AGENTS.md files](/blog/01-agents-md-ai-context) and [DDRs](/blog/02-lets-talk-about-ddrs) to give AI context about patterns and decisions. But there's a gap: these documents describe *how* to work within the codebase, not *what* the current codebase contains. They describe the constraints for adding new functionality but they don't know what else is in the system. What I really needed was a way to give AI a bird's-eye view of the entire system. ## The Problem: AI Sees Trees, Not Forest When I ask an AI to help plan a feature I often need to give it lots of extra context about what we've already got, getting it up to speed with where we are. The things I found myself explaining over and over were what APIs we have, what database tables we have, and how the communication between services works. I was patching over this by adding this stuff to the AGENTS.md files but this information is only sometimes relevant so you're wasting context. I used to ask it to read the important controller files individually before being able to plan with it, but that gets quite impractical for anything other than small targeted changes. On any large project it's easy to have 100s of APIs and loads of database tables, not to mention integration events. No AI is going to read all of that into its context. The most eager AI I've dealt with would easily give up after about 10 files, confidently telling me that it's read all of the files. ## The Solution: Code-Generated Reference Documentation What I needed was an information dense reference document that captures the metadata of the system without requiring the AI to read every source file. Since I work in C# for the backend, I built a tool using Roslyn (Microsoft's .NET compiler platform) to statically analyse my codebase and generate three key reference files: 1. **API Routes** (`api-routes.md`) - Every endpoint with method, route, controller, request/response types, and descriptions 2. **Database Schema** (`database-schema.md`) - Every table with columns, types, indexes, foreign keys, relationships and table descriptions 3. **Event Flow** (`event-flow.md`) - Every integration event with what method publishes the event, what method consumes the event, and what services those are both in. It does take a while to run so currently I have a command line I run to re-create them. A project which has been on the to-do list for a while is to move this to a GitHub action and create a commit back onto main if there were changes, which would run on every commit to main. ## What the Generated Docs Look Like > FYI, all of the tables below have been helpfully populated with dummy data by my friend Claude. ### API Routes Reference ```markdown | Method | Route | Controller | Request Body | Return Type | Auth | Description | | ------ | ----------------------------- | --------------------------- | -------------------- | ---------------- | -------------- | -------------------------- | | POST | `products` | CreateProductController | CreateProductRequest | ProductResponse | Authorized | Creates a new product | | GET | `products/{id}` | GetProductController | - | ProductResponse | Authorized | Retrieves product details | | DELETE | `products/{id}` | DeleteProductController | - | Ok | IsProductOwner | Deletes a product | | GET | `products/{id}/reviews` | GetProductReviewsController | - | ReviewResponse[] | - | Retrieves product reviews | | PATCH | `products/{id}/reviews/{rid}` | UpdateReviewController | UpdateReviewRequest | ReviewResponse | CanEditReview | Updates an existing review | ``` > The routes documentation is a single markdown table with every endpoint ### Database Schema Reference ```markdown ### `products` > Central product catalog entity. Maintains product information #### Columns | Column | CLR Type | DB Type | Nullable | Max Length | Default | Description | Notes | | ----------- | -------------- | ------------------------ | -------- | ---------- | ------- | ------------------------------------------- | ----- | | Id | long | bigint | No | - | - | Gets the unique identifier for this entity. | PK | | Name | string | TEXT | Yes | - | - | The product display name. | - | | Description | string | TEXT | Yes | - | - | Full product description. | - | | Price | decimal | numeric(18,2) | No | - | - | Current product price. | - | | CategoryId | long | bigint | No | - | - | Foreign key to product category. | FK | | CreatedAt | DateTimeOffset | timestamp with time zone | No | - | - | When the product was created. | - | #### Indexes | Columns | Unique | Purpose | | ------------ | ------ | --------------------------------------------------------------------- | | `CategoryId` | No | ProductRepository.GetByCategoryAsync - filtering products by category | | `CreatedAt` | No | ProductRepository.GetRecentProducts - ordering by creation date | #### Foreign Keys | Column(s) | References | On Delete | Relationship | | ------------ | ---------- | --------- | ------------ | | `CategoryId` | Categories | Restrict | Many-to-One | ``` > The database documentation is a single markdown table with every database table ### Event Flow Reference ```markdown | Event | Queue | Publisher(s) | Publisher Source File(s) | Consumer(s) | Consumer Class | | ------------------------ | -------------------------- | ---------------- | ---------------------------------------- | ------------------------------------- | ----------------------------------------------------------- | | `OrderPlacedEvent` | `order-placed-event` | OrderService | OrderAggregateAddedDomainEventHandler.cs | InventoryService, NotificationService | InventoryReservationHandler, OrderNotificationHandler | | `PaymentProcessedEvent` | `payment-processed-event` | PaymentService | ProcessPaymentCommandHandler.cs | OrderService | OrderConfirmationHandler | | `InventoryReservedEvent` | `inventory-reserved-event` | InventoryService | ReserveInventoryCommandHandler.cs | ShippingService, AnalyticsService | ShippingNotificationHandler, InventoryAnalyticsHandler | | `OrderShippedEvent` | `order-shipped-event` | ShippingService | ShipOrderCommandHandler.cs | NotificationService, CustomerService | ShippingNotificationHandler, CustomerOrderUpdateHandler | | `PaymentFailedEvent` | `payment-failed-event` | PaymentService | ProcessPaymentCommandHandler.cs | NotificationService, OrderService | PaymentFailureNotificationHandler, OrderCancellationHandler | ``` > The event flow documentation is a single markdown table with every event in the system > When the AI understands this event flow, it can reason about async processes: "When an order is placed, the inventory is reserved, then shipping is notified." That kind of system-level understanding is impractical without seeing the full event map. ## Benefits for AI-Assisted Development When I want to plan a new feature, I tell the AI to read the three reference files first. The AI can make informed suggestions instead of generic recommendations. When I ask the AI to help with an unfamiliar part of the codebase, the schema documentation provides instant context. "Oh, `Product` has an `IsDiscontinued` field and `DiscontinuedReason` - I can see the lifecycle model without reading the entity class." The event flow documentation is invaluable for debugging and extension. The AI can trace: "When an image uploads, what happens?" It sees the full chain without reading handler implementations. ## Starting Your Own Documentation Generator I'm not able to share or release my generator as it's not a generic thing - it's tied directly into how my project works. I think any generator like this would be tightly coupled to the codebase, or at least ones built on Roslyn would be. If you're working with a large codebase, consider building something similar. The core approach: 1. **Identify what structure matters and isn't easily documented in AGENTS.md** - APIs? Database? Message queues? 2. **Use your language's analysis tools** - Roslyn for C#, ASTs for TypeScript, reflection for Python 3. **Generate structured, scannable output** - Tables work great for AI consumption The goal isn't comprehensive documentation for humans - it's compressed reference material that lets AI understand your system's shape without reading every file. ## Bringing it all together I've added references to the generated docs in my root AGENTS.md: ```markdown ## Generated References - **[API Routes](docs/generated/api-routes.md)** - All API endpoints with methods, routes, controllers, and request/response types - **[Database Schema](docs/generated/database-schema.md)** - All tables with columns, types, indexes, foreign keys, and EF configurations - **[Event Flow](docs/generated/event-flow.md)** - All RabbitMQ integration events with publishers, consumers, and service flows ``` This is another piece of the puzzle I've been building: making AI coding assistants genuinely useful on large codebases. 1. **[AGENTS.md files](/blog/01-agents-md-ai-context)** explain patterns, conventions, and "how to work here" 2. **[DDRs](/blog/02-lets-talk-about-ddrs)** explain decisions, rationale, and constraints 3. **Generated references** explain "what exists" at a structural level Together, they give the AI both the wisdom (patterns/decisions) and the knowledge (current state) needed to work effectively. Combined with [automatic context loading](/blog/03-let-your-ai-load-its-own-context) and [change detection](/blog/04-lineage-mcp), I'm getting closer to AI that truly understands the project it's working on. What approaches have you tried for giving AI visibility into large systems?