You can do better than retrieval
Using graph+vector structure to unlock new patterns in data
Retrieval systems answer questions about what a corpus says. But sometimes the most valuable answers aren’t stored directly. They don’t appear in any document, row, or record. Instead, you’ll find them in relationships, or the lack thereof. You can’t retrieve them: they’re computed.
One of my favorite publicly available data sources is the Washington State Legislature1. In the legislature every bill, sponsor, and roll-call vote is public record, yet the questions an advocate or analyst actually cares about are more strategic. “Who is cross-pressured on this issue?” “Where could a coalition form?” There’s no record in the data that directly answers these questions. Answers exist only as patterns blending semantics and relationships: bill text, sponsorships, votes, and oppositions. Strictly speaking, everything is stored; what’s missing is any record that addresses the question. The answer is derivable, but it’s not something retrievable in a particular record.
I built a system to demonstrate how an agent over a structured data layer can derive answers to questions like these.

Data and Methods
The dataset is one biennium of Washington State legislative activity (2025–26): 713 bills that reached a floor vote, 154 members, ~152k individual roll-call votes, ingested via the WA Legislature’s web services. I organized this data in HelixDB as a property graph with Bill and Member nodes connected by sponsored and voted edges. Every Bill node has an embedding of its digest. This allows retrieval in two ways: semantic search over bill digests, and traversal over relationships. I built a PydanticAI agent with tools for both kinds of search.
Some benefits to this structure are obvious, so I kept the evaluation set short: I wrote 12 questions in three categories. Four each of semantic (“which bills deal with unemployment insurance?”), relational (“which cosponsors of SB 5041 voted against it on final passage?”), and hybrid (“find the major rent-stabilization bill and report how close its Senate vote was”). I evaluated two agents with different tools: the control gets flat vector search over bill digests, and the graph agent gets the same embeddings search plus traversal tools.
The control (vector search only) scored 4/4 on the semantic queries. It’s not a big surprise - retrieval is good as long as there’s a relevant passage with the answer. Also as we’d expect, vector search performed poorly on the relational and hybrid questions, succeeding 0/8 times. It could find the right bill and then say (correctly) that no digest could tell it about voting relationships. The graph agent scored 12/12. This could be useful, but a SQL database with a vector index could tell the same story. The interesting question is more strategic.
Exploring Questions with No Record
I chose a test case without a specific bill of its own. The idea of “regulatory burden” is scattered across legislation for taxes/fees and mandates, so there’s not a single bill to pin it to. Washington State Legislature is under strong party control, which means nearly everything that reaches the floor passes. The interesting signal then is who deviates from party patterns. The query: “I represent a coalition of small business owners concerned about growing regulatory and compliance burden. Which WA legislators should we prioritize for outreach? Focus on themes across bills rather than any single bill.”
The “regulatory burden” idea shows up indirectly: there are mandate and fee bills the coalition would oppose, and relief bills it would support. This means to answer, the agent has to construct the concept before it can query for an answer. It does a series of semantic searches and targeted graph traversals, splitting the landscape into two clusters:
Cost and mandate bills. The relevant bills were HB 2081 (a B&O tax surcharge), SB 5786 (broad license and fee increases), SB 5525 (mass-layoff benefit requirements), and HB 1524 (new workplace-standards duties). They’d increase costs or overhead, so our hypothetical coalition would fight them.
Relief bills. These were near-unanimous: HB 2575 (reduced reporting obligations), SB 5611 and HB 2418 (streamlining permits). Unanimous votes carry no signal, but sponsorship of these bills does. The members who authored these bills chose to be champions for small business relief.
The agent surfaced the swing Democrats who repeatedly crossed party lines on the Cost bills (six House members voted Nay on both HB 2081 and SB 5786) as the highest-value outreach targets, the 22-member bloc that voted Nay on all four mandate bills as the reliable allies, and the Democratic sponsors of the relief bills. For example, it flagged Rep. Edwin Obras, who authored one of the mandate bills and crossed over to vote Nay on another. This sort of signal requires both sponsorships and votes.
The same approach works multi-hop. Provided a query asking who could reach the opposition, the agent walked sponsorship ties outward to identify the crossover Democrats who cosponsor bills with the opposition’s members. Then it searched what those crossovers strongly support, traversing to their sponsored bills and searching the digests for bills related to relief.. In this case, it identified Rep. Adison Richards, who was primary sponsor on bills with Republicans. The clearest thread was HB 1902, a bill creating a permitting-streamlining work group, sponsored by Richards and cosponsored by three of the other crossover Democrats.
Aggregation across bills (voting blocs, crossover counts) ran as structured operations on the data using tool calls, not in the model’s working memory. This allows for structured, grounded reasoning. Each of the agent’s claims can be decomposed into specific edges, and I verified these against the graph.
There was no record the agent could search for stating “Adison Richards is a potential ally on cost-of-doing-business bills.”2 Instead, the agent derived this from semantic similarity, opposition dynamics, and the presence (or absence) of support along party lines.
Why Structure Matters
A flat-vector system can’t do this. It’s not a problem with the embeddings (we use the same embeddings for both agents). But the evidence is distributed across relationships that aren’t encoded in text digests, so this is where the the graph structure comes into play. This isn’t not about using a specific database or tool. I used a graph+vector database, but you could replicate this structure with a SQL database using vector indices and a junction table. The key is that the computation across bills runs as operations against the data instead of in the model’s “head”.
Another benefit is auditability. An LLM asked this question cold may produce a confident answer without grounding. This agent’s answer decomposes into specific graph edges representing how members relate to particular legislation through votes and sponsorship. Each is something I can (and did) verify against the ingested data. In one early experiment, I caught the agent confidently misattributing real votes to the wrong bills (more on that failure and fix in a follow-up post). The resulting data source is rich and auditable, a double win.
Limitations
This is just a demonstration. We’re looking at data from a single legislative session, and I’ve included only floor-vote bills (so anything that failed in committee isn’t present). The step where the agent clusters concepts is interpretive, so the agent's judgment of what counts as "cost" or "relief" is only as good as the model’s reasoning. Ideally, a well-guided system should surface that judgment rather than gloss over it.
Unsurprisingly, prompting also matters: the naive phrasing of the same question produced a single-bill tally. The agent uses these capabilities when the question invited analysis across multiple bills.
Takeaways & Code
The combination of graph and vector structure is usually pitched as a way of extending RAG to relational facts. It’s true, but it undersells the benefits. Stored fact lookup (relational or not) is something databases can always do. But the benefits go one step higher, making the corpus’s latent structure queryable. With the right context and structure, we can explore those unstated patterns and audit what comes out.
The code is available on GitHub. This repository includes the ingest pipeline, graph model, agent tooling, and the eval set with the sample transcripts referenced in this post. The dataset is public record, and the repo has code to retrieve it from Washington State Legislative Web Services.
While preparing to publish this piece, I reviewed the stated policy positions of a few legislators. I don’t think Richards would object to this characterization, based on my review of his campaign’s Issues page. His platform there names B&O taxes and permitting specifically, the two items the agent surfaced from his votes.

