Knowledge Graphs
Knowledge Graphs let you describe categories, types, attributes, and relationships as validated reference data. SyntheticBrew then gives bound agents predictable tools for listing matching records and looking up exact IDs.
Define the domain in JSON Schema, apply it as a bundle, and bind the bundle to an agent. SyntheticBrew generates list_X, get_X, and optional list_X_ids tools for each exposed entity type.
When to use Knowledge Graphs
Section titled “When to use Knowledge Graphs”Knowledge Graphs work for structured, slow-changing domain models. Storage quotas depend on the Cloud plan or Enterprise deployment. They are a good choice for:
- Taxonomies and ontologies — categories → brands → attributes; conditions → symptoms → treatments; jurisdictions → statutes → topics
- Catalogs of typed records — product categories with attributes and brands; legal statutes by jurisdiction; controlled medical terminology
- Known-issue libraries — products → modules → known issues → resolutions
- Cross-referenced reference data — codes, registries, controlled vocabularies
They are not for:
- Inventory or transactional data (20,000 SKUs with real-time stock) → use an external MCP server pointing at your existing system
- Long-form documents and narrative content → use Knowledge / RAG (vector search) instead
- Conversation memory (what the user told the agent) → use Memory instead
How it works
Section titled “How it works”- Define entity schemas in JSON Schema (Draft 2020-12) with SyntheticBrew
x-*annotations - Bulk-import entity instances matching the schemas into a named bundle
- Bind the bundle to one or more agents via the
knowledge_graphscapability - SyntheticBrew generates MCP tools per entity type and makes them available to bound agents
my-bundle/├── manifest.yaml├── schemas/│ ├── category.schema.json│ └── brand.schema.json└── entities/ ├── categories.yaml # array of category entities └── brands.yaml # array of brand entities
After `brewctl kg apply ./my-bundle`:
list_category(filters={popularity: "high"}) → returns matching category records plus the total count.
get_brand(ids=["north-aurora", "missing-brand"]) → returns {entities: [{id, data}], not_found: ["missing-brand"]}. A missing ID does not fail the rest of the batch.Entity schemas
Section titled “Entity schemas”An entity schema is a standard JSON Schema document with SyntheticBrew-specific x-* extension annotations. These annotations identify the primary ID, filterable fields, and references to other entity types.
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "category", "title": "Category", "description": "A product category in the catalog.", "type": "object", "x-id-field": "code", "x-tool-expose": ["list", "get"], "x-tool-description": "Catalog categories. Use list_category to enumerate top-level categories and get_category to fetch one by code.", "required": ["code", "name", "tier"], "additionalProperties": false, "properties": { "code": { "type": "string", "pattern": "^[a-z][a-z0-9_-]{1,30}$", "description": "Lowercase short code.", "x-index": true }, "name": { "type": "string", "minLength": 3, "maxLength": 60 }, "tier": { "type": "string", "enum": ["primary", "secondary"], "x-index": true }, "popularity": { "type": "string", "enum": ["high", "medium", "low"], "x-index": true }, "brand_count": { "type": "integer", "minimum": 0, "x-derived": true } }}See the Schema annotations reference for the full list of x-* annotations.
Auto-generated MCP tools
Section titled “Auto-generated MCP tools”For each entity schema you declare, SyntheticBrew generates up to three retrieval tools:
| Tool | Generated when | Parameters | Returns |
|---|---|---|---|
list_<entity_type> | "list" ∈ x-tool-expose (default) | filters, sort, limit (default 50, max 500), offset | {items: [{id, data}], total, limit, offset} |
get_<entity_type> | "get" ∈ x-tool-expose (default) | required ids array, max 500 | {entities: [{id, data}], not_found: [...]} in input order |
list_<entity_type>_ids | "list_ids" ∈ x-tool-expose (opt-in) | same query controls as list_* | {ids, total} or {items, total} when x-summary-fields is set |
Tools are namespaced per tenant — list_category in tenant A’s bundle is invisible to tenant B. Within a tenant, two bundles cannot expose conflicting tool names; the second apply is rejected with tool_name_collision_in_tenant.
Hard limits on list_* parameters:
limitmust be1..500. SyntheticBrew rejects an explicit out-of-range value; REST returns400, while an agent call receives an error tool result.filterskeys must reference a field markedx-index: truein the schema. Unknown keys are rejected with the allowed-list.- Filter values use JSON types. Tell the agent to send an object rather than a JSON-encoded string and to use record IDs/codes rather than display labels. See Guide the agent to use graph tools.
Cross-references and navigation
Section titled “Cross-references and navigation”The x-ref annotation records that a property refers to another entity type. Apply validates that the target entity type exists in the bundle, but it does not verify that every record value matches an entity. Admin shows the record as JSON; add record-level checks to your bundle workflow when you require strict references.
{ "$id": "brand", "type": "object", "x-id-field": "code", "properties": { "code": {"type": "string"}, "category": { "type": "string", "x-ref": "category" }, "parent_brand": { "type": "string", "x-ref": "brand", "x-ref-field": "code" } }}Cycles between entity types are allowed (A → B → A); they are detected and logged at apply time as a warning, not rejected.
Binding to agents
Section titled “Binding to agents”Enterprise upgrade note. Run the migrations supplied for the target release before binding the capability. See the Enterprise runbook.
A bundle becomes visible to an agent through the knowledge_graphs capability. In a brewctl agent resource, declare the binding like this:
apiVersion: syntheticbrew/v1kind: Agentname: catalog-assistantmodel: glm-5capabilities: - type: knowledge_graphs enabled: true config: bundles: [ecommerce-catalog-example]system_prompt: | You are bound to the "ecommerce-catalog-example" knowledge graph. You have read-only tools: list_category, get_category, list_brand, get_brand, list_product_attribute, get_product_attribute.
MANDATORY workflow on every user question: 1. Identify which entity_type the question is about. 2. Use list_/get_ tools — NEVER invent entity codes or attribute values. 3. If a tool returns 0 results, say so explicitly. Suggest the closest existing entities by querying a related type. 4. Prefer popularity=high categories first when not specified. 5. Cite the entity code of every recommendation.
Filter values must be ENTITY CODES (lowercase snake_case or kebab-case), not display names. Filters is an object, not a JSON-encoded string.For direct REST calls, create the agent first, then attach the binding with POST /api/v1/agents/{name}/capabilities. Configuration import does not accept a nested capabilities field on an agent.
See Guide the agent to use graph tools below. Clear instructions help the model choose graph data instead of answering from general knowledge.
Agents not bound to a bundle do not see its tools. Two agents in the same tenant can be bound to different bundles and see different tools.
Guide the agent to use graph tools
Section titled “Guide the agent to use graph tools”Auto-generated tools are available to the model, but the system prompt still needs to say when they are required. A general instruction such as "You help users navigate the product catalog" does not require the agent to check the graph before answering.
Add an explicit workflow to the agent’s system prompt.
Required workflow
Section titled “Required workflow”Use the following template (adapt the entity-type names to your bundle):
You are bound to the "{bundle_name}" knowledge graph. You have access to theseread-only tools for navigating it deterministically:
list_<entity_type>(filters?, limit?, offset?) → enumerates entities get_<entity_type>(ids=[id, ...]) → batch fetches up to 500 ids
MANDATORY workflow on every user question:
1. Identify which entity_types the question is about. If unclear, call list_<entity_type> on the most general type first to discover the domain. 2. Use the list_/get_ tools to retrieve the actual entities. NEVER invent entity ids, codes, or attribute values from general knowledge. 3. If a tool returns 0 results, say so explicitly. Suggest the closest existing entities by querying a related type (do not fabricate). 4. Prefer popularity=high entities first when the user has not specified. 5. Cite the entity id of every record you recommend, e.g. "north-aurora", so the user can verify.
Filter argument format: - Filter values must be ENTITY CODES (lowercase snake_case or kebab-case identifiers, e.g. category="footwear"), NOT display names ("Footwear"). - `filters` is an object, not a JSON-encoded string. Example call: list_brand(filters={"category": "footwear", "tier": "premium"}, limit=50).Why this matters
Section titled “Why this matters”| Weak prompt | Strong prompt (template above) |
|---|---|
| Agent gives generic catalog advice from training data. | Agent calls list_category first, then drills with list_brand(filters={category: ...}). |
Hallucinated entity codes (e.g. "brand-xyz" that does not exist). | Cited entity codes resolve via get_* to real records. |
| User asks about a niche the bundle does not cover → agent invents one. | Agent says “no premium footwear brands in the catalog yet, closest is mid-tier stride-co” + cites real codes. |
| Filter args with display labels — 0 results, agent spirals through variants. | Filter args use canonical codes — first call returns correct items. |
Test the workflow with known records, missing records, and filters that return no matches. The expected result is an answer based on returned entity IDs, with a clear statement when the graph contains no matching record.
Coexistence with vector knowledge
Section titled “Coexistence with vector knowledge”Knowledge Graphs and the vector Knowledge / RAG primitive are complementary, not competing. The right pattern is to use both together:
| Use case | Primitive |
|---|---|
| ”What categories exist?” (full recall) | Knowledge Graphs (list_category) |
| “Show only premium-tier brands” (filtered) | Knowledge Graphs (list_brand with filters={tier: "premium"}) |
| “How do I care for wool?” (narrative search) | Knowledge / RAG (knowledge_search) |
“What does the brand north-aurora carry?” (deterministic ID lookup) | Knowledge Graphs (get_brand(ids=["north-aurora"])) |
Both capabilities can be enabled on the same agent.
Hybrid pattern: KG + external MCP
Section titled “Hybrid pattern: KG + external MCP”For domains with large transactional data (real-time stock, customer orders, live pricing), put structure in a Knowledge Graph and inventory behind an external MCP server. See the Hybrid pattern guide for full examples.
What to expect
Section titled “What to expect”- Bound agent tools are read-only — generated
list_andget_tools retrieve graph data. Authorized operators and coding agents mutate graphs through the management MCP tools, REST API, orbrewctl; Admin browses graph content. - Schema changes require matching records — after a breaking schema change, re-import entities that conform to the new schema.
- Imports do not prune omitted schemas — a full import replaces the bundle’s entities and updates the schemas it contains, but an older omitted schema remains. Delete and recreate the bundle when retiring an entity type.
- No cross-bundle refs — the entity type named by
x-refmust exist within the same bundle. Record-level reference values are not foreign-key enforced. - Start a new session after tool changes — new graph tools do not appear in a chat that is already in progress.
- Manage access through the agent capability — add or remove bundles in the agent’s Knowledge Graphs capability.
Next steps
Section titled “Next steps”- Quickstart tutorial — get a working graph in 15 minutes
- Schema annotations reference — every
x-*annotation explained - Hybrid pattern guide — combine with external MCP for inventory
- Admin UI guide — inspect bundles and bind them to agents