Skip to content

First Run Tutorial

Synced automatically from seocho/docs/TUTORIAL_FIRST_RUN.md

This tutorial walks through a practical first run:

  1. start services,
  2. verify core APIs,
  3. test rule inference/validation/profile/export,
  4. optionally run agent chat and tracing.
  • Docker + Docker Compose
  • OpenAI API key
Terminal window
cp .env.example .env

Edit .env and set at least:

Terminal window
OPENAI_API_KEY=sk-...
NEO4J_USER=neo4j
NEO4J_PASSWORD=password

Notes:

  • Runtime uses DozerDB image (graphstack/dozerdb) via Neo4j protocol.
  • Keep default ports unless they conflict on your machine.
Terminal window
make up

Check containers:

Terminal window
docker compose ps

Expected key endpoints:

  • Agent API: http://localhost:8001/docs
  • Custom Platform: http://localhost:8501
  • DozerDB Browser: http://localhost:7474
Terminal window
curl -s -X POST http://localhost:8001/run_agent \
-H "Content-Type: application/json" \
-d '{
"query":"What entities exist in the graph?",
"user_id":"tutorial_user",
"workspace_id":"default"
}' | jq
Terminal window
curl -s -X POST http://localhost:8001/run_debate \
-H "Content-Type: application/json" \
-d '{
"query":"Summarize known entities by database",
"user_id":"tutorial_user",
"workspace_id":"default"
}' | jq

If you get “No database agents available”, ingest sample data first (Step 5).

Optionally ensure fulltext index first:

Terminal window
curl -s -X POST http://localhost:8001/indexes/fulltext/ensure \
-H "Content-Type: application/json" \
-d '{
"workspace_id":"default",
"databases":["kgnormal","kgfibo"],
"index_name":"entity_fulltext",
"create_if_missing":true
}' | jq

Then run semantic QA:

Terminal window
curl -s -X POST http://localhost:8001/run_agent_semantic \
-H "Content-Type: application/json" \
-d '{
"query":"Neo4j 에서 GraphRAG 관련 entity 연결을 보여줘",
"user_id":"tutorial_user",
"workspace_id":"default",
"databases":["kgnormal","kgfibo"]
}' | jq

This route runs:

  • question entity extraction
  • fulltext candidate lookup
  • semantic dedup/disambiguation
  • router -> LPG/RDF specialist -> answer generation

Optional (offline ontology hint artifact):

Terminal window
python scripts/ontology/build_ontology_hints.py \
--ontology ./path/to/domain.owl \
--output output/ontology_hints.json

Once generated, semantic reranking auto-loads hints from output/ontology_hints.json or ONTOLOGY_HINTS_PATH.

4. Rule Lifecycle Tutorial (Core New Feature)

Section titled “4. Rule Lifecycle Tutorial (Core New Feature)”
Terminal window
curl -s -X POST http://localhost:8001/rules/infer \
-H "Content-Type: application/json" \
-d '{
"workspace_id":"default",
"graph":{
"nodes":[
{"id":"1","label":"Company","properties":{"name":"Acme","employees":100}},
{"id":"2","label":"Company","properties":{"name":"Beta","employees":80}}
],
"relationships":[]
}
}' | jq
Terminal window
curl -s -X POST http://localhost:8001/rules/validate \
-H "Content-Type: application/json" \
-d '{
"workspace_id":"default",
"graph":{
"nodes":[
{"id":"1","label":"Company","properties":{"name":"Acme","employees":100}},
{"id":"2","label":"Company","properties":{"name":"","employees":"many"}}
],
"relationships":[]
}
}' | jq

First, infer and copy .rule_profile from the response. Then:

Terminal window
curl -s -X POST http://localhost:8001/rules/profiles \
-H "Content-Type: application/json" \
-d '{
"workspace_id":"default",
"name":"company_rules_v1",
"rule_profile":{
"schema_version":"rules.v1",
"rules":[
{"label":"Company","property_name":"name","kind":"required","params":{"minCount":1}}
]
}
}' | jq
Terminal window
curl -s "http://localhost:8001/rules/profiles?workspace_id=default" | jq
curl -s "http://localhost:8001/rules/profiles/<PROFILE_ID>?workspace_id=default" | jq

4.5 Export to DozerDB Cypher constraint plan

Section titled “4.5 Export to DozerDB Cypher constraint plan”
Terminal window
curl -s -X POST http://localhost:8001/rules/export/cypher \
-H "Content-Type: application/json" \
-d '{
"workspace_id":"default",
"profile_id":"<PROFILE_ID>"
}' | jq
Terminal window
curl -s -X POST http://localhost:8001/rules/assess \
-H "Content-Type: application/json" \
-d '{
"workspace_id":"default",
"graph":{
"nodes":[
{"id":"1","label":"Company","properties":{"name":"Acme","employees":100}},
{"id":"2","label":"Company","properties":{"name":"","employees":"many"}}
],
"relationships":[]
}
}' | jq '.practical_readiness'

Interpretation:

  • status=ready: current payload mostly passes and many rules are exportable.
  • status=caution: payload quality is acceptable but governance hardening is still needed.
  • status=blocked: fix failing nodes first, then re-run assess.
Terminal window
docker compose exec extraction-service python demos/data_mesh_mock.py

Then retry /run_debate and graph queries.

Section titled “5.1 Ingest your own raw records (recommended)”

Use the runtime ingestion endpoint:

Terminal window
curl -s -X POST http://localhost:8001/platform/ingest/raw \
-H "Content-Type: application/json" \
-d '{
"workspace_id":"default",
"target_database":"kgnormal",
"records":[
{"id":"raw_1","content":"ACME acquired Beta in 2024."},
{"id":"raw_2","content":"Beta provides risk analytics to ACME."}
]
}' | jq

Then open http://localhost:8501, set mode to semantic or debate, and ask:

  • What does ACME relate to?
  • Show links between ACME and Beta.
Terminal window
make opik-up

Open:

  • Opik UI: http://localhost:5173

Run /run_agent or /run_debate again and inspect spans.

Terminal window
scripts/pm/lint-agent-docs.sh
Terminal window
make down
  • Missing OPENAI_API_KEY on startup:
    • set OPENAI_API_KEY in .env, then make down && make up
  • API not reachable on 8001:
    • docker compose logs extraction-service --tail=200
  • Rule profile not found:
    • verify workspace_id and profile_id
  • Debate returns no agents:
    • ingest data (Step 5) and retry