1. Decoupled skill registry & MCP serving engine
Relic stores, validates, and serves standard team operating procedures (“skills”) to coding agents. Skills are validated against a strict contract, registered in SQLite, moved through a lifecycle (draft → verified → deprecated), and the verified ones are served as MCP tools and resources.
The contract
The
SkillIR Pydantic model is the single source of truth for a skill’s metadata, inputs, outputs, preconditions, safety checks, and citations. The MCP tool input schema is built dynamically from SkillIR.inputs.Lifecycle in SQLite
Skills live in SQLite. When a skill is verified, its
last_verified_at updates and it becomes eligible to be served or written to disk.RecallFn by injection, so the serving package never imports any graph or OpenAI dependency — it keeps serving skills even when FalkorDB is offline.
Reference:
packages/relic-serve/src/relic/serve/mcp_server.py; contract in packages/relic-core/src/relic/ontology/skill_ir.py.2. Deterministic ingestion, token budgeting & a checkpoint ledger
Relic collects issue and PR histories from GitHub and Linear, buffers them in a raw filesystem store, maps them to structured episode specs, and loads them into the graph sequentially — under strict budget control.1
Deterministic mappers
Connectors and
mappers.py run with zero LLM usage, structuring API responses into PrEpisodeBody and IssueEpisodeBody models.2
Token & content bounding
Descriptions are clipped to 2,000 characters, commits to 1,000; bot reviews are dropped and human reviews are capped and filtered. The payload is then fitted to a strict token budget with
_fit_budget.3
Idempotent checkpoint ledger
A ledger tracks already-ingested episodes (e.g.
PR owner/name#42) under ./data/ingest/<group_id>.log. Re-runs skip these entries, making ingestion resilient to interruptions and rate limits.Reference:
packages/relic-ingest/src/relic/ingest/mappers.py and .../ingest/checkpoint.py.3. Per-repo graph partitioning & provenance recall
Knowledge graphs are partitioned by repository using FalkorDB’s multi-database support, and queries return facts with cited issue/PR URLs.Per-repo partitioning
A repo name maps to a safe database name (
buildrelic/relic-core → buildrelic__relic-core). Ingestion clones the Graphiti driver scoped to that database (driver.clone(database=group_id)); search passes the same database = group_id.Fact provenance
Recall maps search hits back to their source episodes via
_resolve_sources, extracting the canonical issue or PR URL (e.g. https://github.com/owner/name/pull/12) to build a fully cited response.Reference:
packages/relic-graph/src/relic/graph/recall.py.The hardest problem
FalkorDB upstream integration and Graphiti patching. Migrating memory storage from embedded Kuzu to FalkorDB unlocked multi-database partitioning and RediSearch full-text support, but introduced two compatibility issues withgraphiti-core 0.29.x:
Empty full-text queries crashed writes
Empty full-text queries crashed writes
Queries containing only stopwords or punctuation generated empty parentheses, crashing write operations.
Hyphens in group IDs broke search
Hyphens in group IDs broke search
Hyphens (e.g.
relic-core) were treated as negation operators, breaking search queries.engram.py by monkeypatching the Graphiti query builders (_patch_falkordb_empty_query) to sanitize empty queries and escape hyphens dynamically before execution.
Performance & DX
Deterministic scorecard
Instead of an LLM-as-judge, the evaluation suite does exact URL matching against gold sets — normalizing trailing slashes and casing — and computes Hit Rate, MRR, and Coverage. Recall tuning stays fast, cheap, and deterministic.
Batched GraphQL fetching
GitHub ingestion moved from many REST calls per PR to a single batched GraphQL query (file changes, reviews, assignees, commits in one trip). Bulk loading routes through Graphiti’s
add_episode_bulk for parallel extraction with deduping.