awgraph — the code graph your agent reads instead of grepping
An agent asked to fix a bug does not know which files matter, so it greps, opens whatever matched, and spends most of its context window on code it will not change. awgraph indexes the repository into a graph of symbols — functions, methods, classes, their calls and callers — and answers a natural-language task with the handful of chunks that task actually needs.
pip install awgraph
Python 3.10+. Nothing else is required to index and query.
What it costs, measured
The interesting question is not "is a graph better than grep" — it is what does each cost. Measured on a corpus of real commits, where the task is a commit message with the answer filenames stripped out and the truth is the set of files that commit actually modified:
| retriever | recall@10 | context tokens per task |
|---|---|---|
| ranked multi-term grep | 0.933 | 351,369 |
| awgraph | 0.800 | 1,503 |
86% of grep's recall for 0.43% of the context — a 234x reduction.
Read that honestly: grep still wins on recall. awgraph is not a better finder; it is a dramatically cheaper one, and on a long agent loop the context budget is usually what runs out first. If you need maximum recall and cost is no object, grep. If you are paying per token across thousands of turns, this is a different order of magnitude.
Caveats, because a benchmark without them is marketing: n=15 tasks, and only 33.3% of chunks carried embeddings on that run, so the semantic half was working at partial strength — the recall number understates it.
A naive fusion (run the graph, fall back to grep when it returns few files) was also measured: it reaches grep's 0.933 recall at 352,872 tokens — more than grep alone, because the fallback fires on nearly every task and pays both bills. Reported because it did not work; a smarter trigger is future work.
Setup: index once, embed lazily
Two costs, and only one of them scales with repo size.
| step | 2,400 chunks | 43,730 chunks |
|---|---|---|
| parse + index | 49.8s | 75.5s |
| embed (CPU) | — | ~97 min at ~450 vectors/min |
Indexing is close to size-insensitive — 27x the files for 1.5x the time, because parsing runs across workers. Embedding is the part that hurts on CPU, so it is optional, cached and incremental: re-indexing reuses stored vectors and only embeds what changed.
Without any embedding backend, queries fall back to keyword scoring and still work. That fallback is silent by design and dangerous by nature — a graph with no vectors looks like a working graph that is merely worse. Check coverage rather than assuming it:
embedded = sum(1 for c in graph.chunks.values() if c.embedding is not None)
print(f"{embedded}/{len(graph.chunks)} chunks carry vectors")
Use it
import asyncio
from awgraph import CodeGraph
async def main():
graph = CodeGraph(root_path="/abs/path/to/repo", auto_index=False)
await graph.index_codebase("/abs/path/to/repo") # absolute path required
for chunk in await graph.hybrid_query("retry with exponential backoff", max_results=5):
print(chunk.name, chunk.source_path, chunk.start_line)
asyncio.run(main())
index_codebase needs an absolute path. Given a relative one it walks
nothing, indexes zero chunks, and returns successfully — so assert on
len(graph.chunks) rather than on the absence of an exception.
The query does not need to contain the symbol name. Asking for "backoff policy for flaky calls" against a class documented as "Backoff policy for flaky calls" returns it by meaning, not by string match.
Where it sits
Three packages, three different questions about the same repository:
- awgit — semantic version control. Stable node ids, semantic edit-ops, leases so concurrent agents do not overwrite each other, stacked commits with one PR each. It knows what changed and who is editing it.
- awgraph — code intelligence. Symbols, call paths, dependencies, blast radius. It knows what the code is and what depends on what.
- aither-adk — the agent runtime that consumes both.
The seam is the useful part: awgit tells you a commit touched
RetryPolicy.next_delay; awgraph tells you what calls it and which tests cover
it; the agent reads that instead of the repository.
Related work
GitNexus is the closest analogue and worth reading. Its recommended mode augments grep with graph context rather than replacing grep — a conclusion these measurements independently reach. Note its licence is PolyForm Noncommercial (source-available, commercial use forbidden), where awgraph is Apache 2.0. Its published figures measure SWE-bench task resolution; the numbers above measure retrieval recall. Those are different axes and should not be compared directly.
Licence
Apache 2.0.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file awgraph-1.0.0.tar.gz.
File metadata
- Download URL: awgraph-1.0.0.tar.gz
- Upload date:
- Size: 84.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32de7c8cf0cd00c96d1e2be85ff05ce0aa3e64e9994e331fede8db7439a3800c
|
|
| MD5 |
dcdc62eaf6d6eba14feda618575cc50c
|
|
| BLAKE2b-256 |
c934790169dc914194d1f85d39f5fb19d880ee09a6d714e1474b294884e2568a
|
Provenance
The following attestation bundles were made for awgraph-1.0.0.tar.gz:
Publisher:
pypi-publish.yml on Aitherium/awgraph
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
awgraph-1.0.0.tar.gz -
Subject digest:
32de7c8cf0cd00c96d1e2be85ff05ce0aa3e64e9994e331fede8db7439a3800c - Sigstore transparency entry: 2501135180
- Sigstore integration time:
-
Permalink:
Aitherium/awgraph@0fe02ce5c7888f6393a40753160784f21f3733e3 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Aitherium
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@0fe02ce5c7888f6393a40753160784f21f3733e3 -
Trigger Event:
release
-
Statement type:
File details
Details for the file awgraph-1.0.0-py3-none-any.whl.
File metadata
- Download URL: awgraph-1.0.0-py3-none-any.whl
- Upload date:
- Size: 83.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
501f0145ef6970d34d295093321158d433b0a57861e3293c3f2c14fe0fd37d13
|
|
| MD5 |
1d6405c0ff19cc16549defc8759dca31
|
|
| BLAKE2b-256 |
bad67255ca58f0063a5efae5919750ed6e771952ba2e900331c199673dfa6844
|
Provenance
The following attestation bundles were made for awgraph-1.0.0-py3-none-any.whl:
Publisher:
pypi-publish.yml on Aitherium/awgraph
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
awgraph-1.0.0-py3-none-any.whl -
Subject digest:
501f0145ef6970d34d295093321158d433b0a57861e3293c3f2c14fe0fd37d13 - Sigstore transparency entry: 2501135196
- Sigstore integration time:
-
Permalink:
Aitherium/awgraph@0fe02ce5c7888f6393a40753160784f21f3733e3 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Aitherium
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@0fe02ce5c7888f6393a40753160784f21f3733e3 -
Trigger Event:
release
-
Statement type: