Files
koios/prompts/tools/neo4j.md
Robert Helewka 703b3402d4 docs(readme): update assistant roster, prompt layers, repo structure
- Update assistant lists (added Shawn, Watson, David, CASE, AWS SA; modified Scotty/Harper roles)
- Reflect new architecture layers: Tool Prompt Snippets and Shared Context
- Align repository structure diagram with current filesystem layout
2026-05-20 22:50:22 -04:00

70 lines
3.5 KiB
Markdown

# Neo4j (knowledge graph + inter-agent messaging)
The Neo4j knowledge graph is shared across all assistants. Read broadly; write to nodes you own (see your team's graph context).
## Writing discipline
- **Always MERGE on `id`** to make writes idempotent. Never blind-create.
- **Use the canonical ID format:** `{type}_{identifier}_{qualifier}` (e.g., `infra_neo4j_prod`, `proto_mcp_dashboard`, `note_2026-05-20_harper_scotty_prod_handoff`). Lowercase, snake_case.
- **Always set timestamps.** `ON CREATE SET n.created_at = datetime()` for new nodes; `SET n.updated_at = datetime()` on every write.
- **Check before creating.** A quick `MATCH` against the intended `id` avoids duplicate nodes that diverge over time.
## Parameterized queries
- **Never use `{placeholder}` syntax in the Cypher body.** Local models (Qwen3.5-35B) mishandle it. Pass values through `params`, and use `$name` in the query:
```cypher
// good
MERGE (n:Note {id: $id})
SET n.title = $title, n.updated_at = datetime()
```
```cypher
// bad — do not do this
MERGE (n:Note {id: '{id}'})
SET n.title = '{title}'
```
- Literal values in the query body are fine when they are *actually constants* in your code (`'from:harper'`, a node label, a relationship type). The rule is no template interpolation into the query string.
## Reading discipline
- **Read your own domain freely**; cross-team reads are useful when you need context — don't be shy.
- Use `LIMIT` on exploratory queries. Returning the whole graph kills latency and burns tokens.
### Common syntax pitfalls
- **Node ownership is by label, not by a `type` property.** Harper's nodes are `:Prototype` and `:Experiment` (label = ownership). Scotty's are `:Infrastructure` and `:Incident`. There is no `n.type = 'harper'` filter; the label is the filter. The `type` property only appears on `Note` nodes (e.g., `n.type = 'assistant_message'` for messaging) — do not generalize that pattern.
- **`MATCH ... OR MATCH ...` is not valid Cypher.** You cannot OR-combine match patterns at the top level. To query alternative structures, use `UNION` or `OPTIONAL MATCH`:
```cypher
// UNION — three separate queries, same return columns, results combined
MATCH (n:Prototype)-[:DEMONSTRATES]->(t:Technology)
RETURN n.id AS id, n.name AS name, t.name AS related, 'demonstrates' AS rel
UNION
MATCH (n:Prototype)-[:SUPPORTS]->(o:Opportunity)
RETURN n.id AS id, n.name AS name, o.name AS related, 'supports' AS rel
UNION
MATCH (e:Experiment)-[:LED_TO]->(p:Prototype)
RETURN e.id AS id, e.title AS name, p.id AS related, 'led_to' AS rel
```
```cypher
// OPTIONAL MATCH — one row per starting node, with nulls where a relationship doesn't exist
MATCH (n:Prototype)
OPTIONAL MATCH (n)-[:DEMONSTRATES]->(t:Technology)
OPTIONAL MATCH (n)-[:SUPPORTS]->(o:Opportunity)
RETURN n.id, n.name, collect(DISTINCT t.name) AS technologies,
collect(DISTINCT o.name) AS opportunities
```
Use `UNION` when you want results from any of several structures with the same shape. Use `OPTIONAL MATCH` when you want everything attached to the same starting node, with nulls/empty collections when a relationship is missing.
## Error handling
If a graph query fails, continue the conversation. Mention the failure briefly. Never expose raw Cypher errors to the user.
## Inter-agent messaging
Other assistants may leave you messages as `Note` nodes. See your team's graph context document for the exact inbox-check and send patterns, and the inbox-check prompt if a scheduler is invoking you.