Two records. One failed pickup. Two different explanations.

“Pickup cancelled by customer.”

“Pickup failed because the courier was unavailable.”

This is a fictional example from ReturnTrail, the project we built for WeMakeDevs × FalkorDB Graph Hacks.

Finding different words is the easy part. The useful questions come next: do these records describe the same pickup attempt? What did an earlier reply actually explain? If another document arrives, does that old explanation still cover the evidence?

Those questions shaped our graph model, our investigation tools and the way we handle “resolved” tasks.

Try ReturnTrail · Source code and setup

ReturnTrail practice workspace showing two original sources and a pending pickup question

Product capture using fictional records and a local FalkorDB instance. Case API responses were not mocked for this capture.

The job we chose

ReturnTrail helps a shopper prepare an evidence-linked support conversation about a disputed return pickup.

The output is a reviewable brief: original claims, their source connections, follow-up questions and the history of manual explanations. We keep those explanations separate from the records they describe.

Our current prototype uses four seeded fictional cases and bounded fictional text additions. We have not validated customer demand or measured real-world dispute outcomes. The hackathon gave us a focused implementation to put in front of users.

Why the pickup attempt belongs in the graph

An order can have more than one pickup attempt. Different failure reasons on different attempts need not contradict each other.

Our graph connects:

  • A case to its order, item and return request.
  • Each pickup attempt to its return request.
  • Each statement to the pickup it describes and the document that recorded it.
  • Each follow-up action to its reviewed documents.
  • Each manual clarification to its follow-up action.

Here is the evidence query documented in the repository:

MATCH (c:Case {id:$caseId})-[:HAS_ORDER]->(o:Order)-[:CONTAINS]->(i:Item) MATCH (c)-[:HAS_RETURN]->(r:ReturnRequest)-[:RETURNS]->(i) MATCH (p:PickupAttempt)-[:ATTEMPTS]->(r) MATCH (s:SupportStatement)-[:ABOUT]->(p) MATCH (s)-[:RECORDED_IN]->(d:EvidenceDocument) RETURN DISTINCT c.id AS caseId, o.id AS orderId, i.id AS itemId, r.id AS returnId, p.id AS pickupId, s.id AS statementId, s.claimedStatus AS claimedStatus, s.text AS statement, d.id AS evidenceId, d.sourceType AS sourceType ORDER BY evidenceId, statementId; 

The backend chooses the authorized workspace graph and binds the case ID. Both ownership paths through the order/item and return/item must match. The API exposes source connections derived from the executed query results.

CASE-002 is our negative example: records describe separate pickup attempts, so the supported rule does not flag them as a same-attempt disagreement.

FalkorDB supplies the evidence traversal and stored workflow context. Java applies explicit rules to the returned records.

What an earlier explanation actually covers

Our most useful design decision was connecting a saved action to the documents it reviewed:

Case → Action → REFERENCES → EvidenceDocument

A manual reply is linked through:

Action → HAS_CLARIFICATION → ClarificationRecord

This lets us ask a more precise question than “Was this task resolved?”

Does the reviewed source set, including its evidence revision, match the current source set?

In our implementation, coverage requires a nonempty current source set, matching evidence IDs and a matching revision. The ContextCoverage implementation exposes reviewed sources, newly added sources, task state and saved-note context.

A later document can therefore require fresh review while the earlier task remains resolved in history. We preserve what happened instead of rewriting the old task as if it had reviewed information that did not exist yet.

A matching source set still does not verify a manual explanation. It establishes its context boundary.

Context lab: preview the missing connection

Context lab lets a user temporarily set aside one source and inspect the result.

For CASE-001, setting aside DOC-001 leaves only the courier-unavailable claim. Our bounded disagreement rule no longer has two conflicting reasons to compare.

The application runs a parameterized, read-only graph query with a source exclusion. It returns the remaining evidence connections and evaluates that result. Original records and saved tasks stay unchanged.

Context lab showing the full source set beside a preview excluding DOC-001

This is a diagnostic preview. It does not establish that the excluded document is false or that the remaining claim is true. It shows how the available evidence changes the supported next question.

CASE-004 extends the demonstration: add a reviewed fictional source to a case with an earlier manual reply, then inspect the changed coverage.

The agent's job is bounded

Our Spring Boot backend exposes four investigation tools:

  1. get_case_evidence
  2. get_case_clarifications
  3. get_case_findings
  4. prepare_followup_action, when a finding is pending

The AI workflow must retrieve the current evidence and saved context before proceeding to findings and a local follow-up action. The backend enforces the sequence and renders the final report from tool results.

These are application tool calls. We did not build an MCP server, and the model does not generate arbitrary Cypher or decide who caused the failed pickup.

A separate Review rules & prepare question action performs the deterministic workflow without a model request. Users can then record an explicit manual outcome and export a fresh brief. The application does not send that draft to a courier or issue a refund.

What we tested—and what those tests establish

We tested the distinctions that could otherwise produce a misleading answer: same versus different attempts, unknown reasons, changed source context, stale writes and workspace isolation.

Recorded check Scope
93 backend tests successful; 2 skipped Hosted default suite at commit 275fb37; zero failures or errors
14 frontend tests passed Domain, draft and public-video input boundaries
Five public API workflow groups passed Actual hosted application and external FalkorDB; synthetic writes, history, retries, version protection and guest isolation
One real hosted AI investigation passed Four model requests, all four required tools in order and one OPEN local follow-up

The validation record distinguishes mocked contracts, actual graph checks and the hosted model request. The twenty labelled synthetic rule fixtures are a regression set, not an accuracy benchmark.

A deployment lesson: readiness has a limited meaning

When we enabled OAuth providers, the graph readiness endpoint stayed UP while the homepage returned HTTP 500.

The authorization resolver was treating an ordinary page path as a possible provider path. At the root URL, that produced an empty registration ID. We reproduced the exception, restricted lookup to OAuth authorization routes and added three regression tests.

That failure changed our release check: we verify the homepage, sign-in shell, provider redirects and a fresh guest workflow alongside database readiness.

The backend and frontend run together on Render; the graph runs on FalkorDB Cloud. The current free preview can lose sessions and graph data. Its database tier has no TLS, persistence or backups, so it is an evaluation environment for fictional data, with no durable-account promise. See hosting boundaries before using or reproducing it.

Try the part that changes the next action

Open the demo as a guest and start with CASE-001:

  1. Compare the original claims in Evidence.
  2. Inspect their paths in Connections.
  3. Set aside one source in Context lab and compare the assessment.
  4. Prepare the question, record a fictional manual outcome and export Case brief.

Then try CASE-002 and CASE-004. The interesting outcome is whether the graph context supports another question, and which sources make that question necessary.

Next, we want to observe nontechnical users completing this brief workflow and speak with support operators about the information they need. We need those observations before claiming that the product saves time or fits an operational process.

The lesson we are taking forward is specific: a saved answer needs a record of the evidence it covered. When that evidence changes, the application should make the boundary visible.

Built by Om Singh Jadon and Ajeet Gadekar for WeMakeDevs × FalkorDB Graph Hacks, under Agents That Act on Connected Data.

ChatGPT assisted with planning, implementation.

Explore: Live demo · Repository · Cypher queries · FalkorDB documentation