A clean and modular pipeline to ingest UserIntent and Bid JSON data into a Neo4j Knowledge Graph. This enables multi-hop traversal, reasoning, and GraphRAG integration for AI/LLM agents.
- Python 3.10+
- Neo4j 5.x
- No external dependencies (uses only
neo4jdriver)
Nodes:
Account { address }UserIntent { intentHash, status, ... }Bid { bidHash, status, pathSummary, ... }Solver { address }Token { address }
Relationships:
(Account)-[:PLACED]->(UserIntent)(Solver)-[:RESPONDED_WITH]->(Bid)(Bid)-[:BID_FOR]->(UserIntent)(UserIntent)-[:USES_ASSET]->(Token)(UserIntent)-[:DESIRES_ASSET]->(Token)(Bid)-[:TRANSFER_STEP { action, amount, sequence }]->(Token)
- Multi-hop traversal:
Bid → Intent → Account - Subgraph reasoning for LLMs
- Directional relationships (e.g.
RESPONDED_WITH) - Natural for path finding, solver trust scoring, traceability
-
Install Python dependencies:
uv pip install -r requirements.txt
This will install the required Python packages, including the Neo4j driver.
-
(Optional) Use Makefile for convenience: You can use the provided Makefile to automate setup and ingestion:
make install # Installs dependencies make start-db # Starts Neo4j with Docker Compose make ingest # Runs the ingestion script make run-all # Installs, starts DB, and runs ingestion in one step
-
Ensure Docker is installed: Docker is required to run Neo4j using Docker Compose.
-
Check your Neo4j credentials: Make sure the password in
sample_run.pymatches the one set in yourdocker-compose.yml.
-
Start Neo4j with Docker Compose:
docker-compose up -d
This will start the Neo4j database in the background.
-
Check Neo4j startup logs to ensure it started successfully:
docker logs --follow neo4j-graph
Look for a line like
Remote interface available at http://localhost:7474/which indicates Neo4j is ready. -
Run the main ingestion script:
make run
-
Start API Layer for REST Calls
uvicorn api.cypher-api:app --reloadA UserIntent represents a user's desired action or transaction in the system. It captures the user's requirements, constraints, and preferences for an operation (such as a token swap or transfer). Each UserIntent is uniquely identified by an intentHash.
Key Fields:
intentHash: Unique identifier for the intent.intentStatus: Current status (e.g.,BID_SUBMITTED).account: The address of the user who created the intent.userIntent.core.permittedAccounts: List of accounts allowed to act on this intent.userIntent.constraints: Constraints such as permitted chains, deadline, max gas, slippage, desired assets, and dispensable assets.createdAt,updatedAt: Timestamps for creation and updates.
Example:
{
"intentHash": "0x0ed5c65e5ef42fa996298fcb22592f3be1b44b1dfd6edba839879463f554838e",
"intentStatus": "BID_SUBMITTED",
"account": "0x448b47F358dA18749529bDeAeC26322E58D13177",
"userIntent": {
"core": {
"permittedAccounts": [
{ "account": "0x23F04522a2ec5a8b188C48c18edAE54005b537a3", "chainId": 8453 }
]
},
"constraints": {
"permittedChains": [42161],
"deadline": 1751304211,
"maxGas": 6000000,
"slippagePercentage": 5.0,
"desiredAssets": [
{ "asset": "0xfdfff924c413a228c9fc62b1978ed8f755d81111", "value": "500000000000000000000", "chainId": 8453 }
],
"dispensableAssets": [
{ "asset": "0xaf88d065e77c8cc2239327c5edb3a432268e5831", "maxValue": "100000", "chainId": 42161 }
]
}
},
"createdAt": "2025-06-30T17:22:33.914788126"
}A Bid is a response to a UserIntent from a solver or service provider. It proposes a way to fulfill the user's intent, including the steps and assets involved. Each Bid is uniquely identified by a bidHash and references the intentHash it is responding to.
Key Fields:
bidHash: Unique identifier for the bid.intentHash: TheUserIntentthis bid is for.solverAddress: Address of the solver making the bid.smartWalletAddress: Address of the smart wallet used.bidStatus: Status of the bid (e.g.,PENDING).bid.steps: Sequence of actions (with tokens, amounts, and actions).createdAt,updatedAt: Timestamps for creation and updates.
Example:
{
"bidHash": "0xc999e8523aa6400c4d2421e26ab51d8100f6a3df83b1ccbdfcf8a04b91129baf",
"intentHash": "0x0ed5c65e5ef42fa996298fcb22592f3be1b44b1dfd6edba839879463f554838e",
"solverAddress": "0x7C84F10502FcDea2E403b70feA96a4aE990a34DF",
"smartWalletAddress": "0x23F04522a2ec5a8b188C48c18edAE54005b537a3",
"bidStatus": "PENDING",
"bid": {
"steps": [
{
"sequenceNumber": 1,
"chainId": 8453,
"solution": {
"to": "0xfdfff924c413a228c9fc62b1978ed8f755d81111",
"callData": "...",
"value": "0",
"path": {
"tokenConsumed": "0xfdfff924c413a228c9fc62b1978ed8f755d81111",
"amountConsumed": "500000000000000000000",
"tokenReceived": "0xfdfff924c413a228c9fc62b1978ed8f755d81111",
"amountReceived": "500000000000000000000",
"action": "TRANSFER"
}
}
}
]
},
"createdAt": "2025-06-30T17:22:36.791050721"
}- Each
UserIntentcan have multiple Bids from different solvers. - Each
Bidreferences theintentHashof theUserIntentit is responding to. - In the graph, this is modeled as:
(Account)-[:PLACED]->(UserIntent)<-[:BID_FOR]-(Bid)<-[:RESPONDED_WITH]-(Solver)
This structure enables efficient multi-hop traversal, reasoning, and traceability in the knowledge graph.
