ilo: A Programming Language for AI Agents, Not Humans

Six Ways to Give an AI Agent a Map of Your Code

AI agents read too much code to do small tasks. An agent asked to modify one function in a 3,000-line file loads the entire file. An agent exploring a new repo reads dozens of files before it understands the structure. Context windows fill up with code the agent never needed.

Every tool in this post attacks the same problem: index the codebase first so the agent can request only the symbols it needs.

The tools

jCodeMunch

jCodeMunch parses source files with tree-sitter, extracts every symbol (function, class, type, constant), and stores them in a JSON index. Agents request individual symbols by ID instead of reading files. Each response includes token accounting.

The numbers from a real benchmark: finding a function drops from ~40,000 tokens to ~200. Understanding a module’s API drops from ~15,000 to ~800. About 80% reduction overall, or 5x efficiency.

It’s a flat symbol index. No relationships between symbols, no call graph, no type information. You get surgical extraction of individual definitions.

SymDex

SymDex does what jCodeMunch does, plus semantic search and call graph analysis. It stores symbols in SQLite with vector embeddings, so agents can search by intent (“validate email”) rather than exact name. It also indexes HTTP routes from Flask, FastAPI, Django, and Express.

Claims 97% token reduction per lookup. Supports 14+ languages, live reindexing via file watching, and cross-repo search from a single instance.

The addition of semantic search matters. An agent that doesn’t know the function name can still find it. That cuts a round trip that would otherwise cost thousands of tokens in exploratory reads.

CodeGraphContext

CodeGraphContext goes further than symbol extraction. It indexes code into a graph database where nodes are symbols and edges are relationships (calls, imports, inheritance). Agents query for callers, callees, class hierarchies, and call chains.

It supports 14 languages, live file watching, and generates interactive knowledge graph visualisations. Available as both a CLI and an MCP server.

The graph structure means an agent can ask “what calls this function?” without reading every file. That’s a qualitative difference from flat symbol indexes.

Prowl

Prowl is a desktop app that builds an interactive knowledge graph of your codebase. It uses tree-sitter for parsing and KuzuDB for graph storage, with local embeddings for semantic search. 19 MCP-exposed query functions cover impact analysis, blast radius tracing, Cypher queries, and change detection.

Measured 90.5% token reduction for full project understanding (84,795 to 8,035 tokens) and 93.2% for multi-step research tasks.

It’s the most feature-rich option. Built-in AI chat, code editor, terminal, GitHub repo comparison. The tradeoff is complexity: it’s an Electron app, not a lightweight MCP server.

CodeBoarding

CodeBoarding takes a different angle. Instead of symbol-level indexing, it generates high-level architectural diagrams. Static analysis plus LLM agents produce Mermaid.js visualisations showing how components, layers, and modules relate.

It’s not a query tool. You don’t ask it for a specific function. You ask it to explain the architecture of PyTorch or FastAPI, and it produces a diagram. Useful for onboarding and documentation, less useful for an agent modifying code.

Memgraph GraphRAG

Memgraph’s approach uses a full graph database (Memgraph) with tree-sitter parsing to build a code graph, then lets agents query it with natural language that gets translated to Cypher. The demo showed it answering “what is the maximum function call chain in this repo?” with a precise answer of 11.

The hybrid search strategy is interesting: simple questions get grep-style search, structural questions get Cypher queries. The graph database handles the routing.

What they have in common

Every tool follows the same pattern:

  1. Parse source code (usually tree-sitter)
  2. Index symbols and/or relationships
  3. Serve targeted queries over MCP
  4. Measure token savings vs reading raw files

The differences are in what gets indexed (symbols only vs relationships vs architecture) and how queries work (exact lookup vs semantic search vs graph traversal).

Where ilo graph fits

ilo graph is built into the ilo language compiler. It doesn’t index external codebases. It analyses ilo programs specifically, using information that’s only available because the language was designed for it.

# Full program graph: all functions and types, signatures only
ilo graph program.ilo

# One function plus its direct dependencies
ilo graph program.ilo --fn build-order

# Transitive subgraph: everything build-order depends on
ilo graph program.ilo --fn build-order --subgraph

# Budget-constrained: fit within 500 tokens
ilo graph program.ilo --fn build-order --budget 500

# Reverse: who calls subtotal?
ilo graph program.ilo --fn subtotal --reverse

The output is JSON. Every function includes its signature, direct calls, reverse callers, and types used. The --budget flag does token estimation and truncates the subgraph to fit a limit, returning a list of what got cut.

This is possible because ilo’s type system and explicit imports make the call graph derivable from the AST without execution. use "auth.ilo" [vld-email vld-plan] declares exactly what’s imported. Every function signature declares its types. There’s no dynamic dispatch, no implicit imports, no globals to track.

The five principles from the ilo manifesto explain why this matters. Principle 5, “Graph-Reducible,” was designed specifically for this:

Writing code costs the same tokens regardless of program size. But reading code scales with program size. ilo makes the dependency graph explicit and queryable, so the agent loads only what it needs.

An agent modifying one function in a 30-function program loads the target function’s source, its dependencies’ signatures, and the types it references. Benchmark results show 40-70% reduction compared to loading the full file.

Different problems, different tradeoffs

These tools sit on a spectrum:

ToolIndex typeQuery modelToken savingsScope
jCodeMunchFlat symbolsExact lookup~80%Any language
SymDexSymbols + embeddingsSemantic search~97%Any language
CodeGraphContextSymbol graphGraph queriesNot publishedAny language
ProwlFull knowledge graphCypher + semantic~90-93%Any language
CodeBoardingArchitectureDiagram generationN/AAny language
Memgraph GraphRAGFull code graphNL to CypherNot publishedAny language
ilo graphCall + type graphSubgraph extraction~40-70%ilo only

The external tools (everything except ilo graph) share a constraint: they work with languages that weren’t designed for graph analysis. Python has dynamic imports, monkey patching, getattr. JavaScript has require with computed paths, prototype chains, dynamic this. These tools use tree-sitter to approximate the call graph, but they can’t know everything statically. The graph has holes.

ilo graph has no holes. The call graph it extracts is complete because every dependency is declared and every type is explicit, so nothing is hidden behind dynamic dispatch or implicit imports.

The tradeoff: ilo graph only works with ilo, while the external tools work across many languages.

Which approach wins

For existing codebases in Python, TypeScript, Java, or Go, the external tools are the only option. Among them, the choice depends on what the agent needs. Flat symbol lookup (jCodeMunch, SymDex) is fast and cheap. Graph queries (CodeGraphContext, Prowl, Memgraph) answer structural questions that flat indexes can’t.

For new programs where correctness matters and the agent is generating code, ilo’s approach has an advantage the external tools can’t replicate. The graph isn’t approximate. The budget constraint ensures the agent never overloads its context. The type signatures serve as contracts that let the agent understand a dependency without reading its implementation.

The external tools retrofit graph analysis onto languages that didn’t anticipate it. ilo bakes it in, so the graph extracted at compile time is exact rather than approximate.