Skill Injection
Skills are specialized knowledge packages that augment agent capabilities during execution. AEGIS uses a tiered injection architecture that progressively loads more context as needed, with an injection ledger to prevent duplicate content.
Skills are the domain-neutral unit of configurable agent behavior. Live skill definitions, routers, rules, and personas are tenant-configurable data served by agent-config-service, and compliance domains ship as installable packs. The RRC oil & gas skills named on this page (spacing, offset wells, filing assembly) are the first installed vertical’s content — the mechanism is not RRC-specific.
R36 — selection is message-driven. The legacy skill_select_node / skill_inject_node pipeline hop, which scanned assistant output for a selection marker, was deleted. The marker is tombstoned as SKILL_SELECT_MARKER_TOMBSTONE in orchestration/tools.py — never emitted, never scanned. Skills are now selected via two explicit tools, pull_routers and select_skill, inside the ordinary tool loop. See Selection Flow (R36) below.
Tier Architecture
The skill system has four tiers, each adding more context at increasing token cost:
Tier 1 (~50 tokens) Tier 2 (~200-800 tokens) Tier 3 (variable) Tier 3.5 (variable)
+------------------+ +---------------------+ +------------------+ +------------------+
| Manifest | | Full Definition | | Artifacts | | Graph Context |
| | | | | | | |
| - skill_id | --> | - description | --> | - Reference docs | --> | - Well data |
| - name | | - steps (ordered) | | - Templates | | - Lease/field |
| - description | | - requirements | | - Regulatory text| | - Operator |
| - triggers | | - output_format | | - Examples | | - Offsets |
| - domain_tags | | - hitl_checkpoints | | - Token estimate | | - Regulations |
+------------------+ +---------------------+ +------------------+ +------------------+
Always loaded in Loaded when the LLM Loaded alongside Loaded from knowledge
system prompt (compact) selects the skill Tier 2 if artifacts graph if entity context
(R36: select_skill) exist for the skill is availableTier 1: Manifest
The manifest is a compact summary (~50 tokens) that is always available in the system prompt. It tells the LLM what skills exist and when to request them.
{
"skill_id": "spacing-calculation",
"name": "Spacing Calculation",
"description": "Calculate distances from proposed well to lease lines and offset wells",
"triggers": ["spacing", "distance", "lease line", "offset distance", "467 feet"],
"domain_tags": ["spacing", "rule_37", "drilling"]
}Tier 2: Full Definition
Loaded on demand when the LLM requests the skill. Contains the complete specification:
{
"description": "Calculates the distance from a proposed well surface location...",
"steps": [
"Retrieve the subject well location from the knowledge graph",
"Identify the lease boundaries and compute distance to each lease line",
"Find all wells on the same lease and compute well-to-well distances",
"..."
],
"requirements": [
"Well must have surface_location coordinates in the knowledge graph"
],
"output_format": "Spacing Summary:\n- Distance to nearest lease line: X ft..."
}Tier 3: Artifacts
Reference documents stored in the skill_artifacts table. These are loaded alongside the Tier 2 definition when available. Examples include regulatory text excerpts, form templates, calculation examples, and filing precedent.
Each artifact has:
name: Human-readable labelcontent: Full text contentcontent_hash: SHA-256 hash for change detectiontoken_estimate: Approximate token count for budget tracking
Tier 3.5: Graph Context
Entity-specific context assembled from the knowledge graph. Based on the well API number or entity ID in working memory, the context assembler queries the graph for:
- The entity and its properties
- Related entities (lease, field, operator)
- Offset wells within regulatory distance
- Active flaring authorizations
- Applicable regulations
- Connected infrastructure (wellpad, facilities, pipelines)
The sections included depend on the skill’s domain_tags. See Knowledge Graph - Context Assembly for the domain-to-section mapping.
Selection Flow (R36)
Skill selection happens through two tools defined in orchestration/selection_tools.py, offered only to general-mode runs (an agent_definitions row with root_skill_key = NULL). Agent-mode runs (rule_37, rule_32) load their root skill at conversation start and never pull routers.
System prompt (index-0 block, sealed at conversation birth)
AVAILABLE SKILL ROUTERS manifest
router_key + recruitment_blurb per active router
|
v
pull_routers(router_keys[]) --> full skill descriptions per router
(derived read: approved skill_router_map rows x active skills
x latest-approved skill_description_versions row per skill)
|
v
select_skill(skill_key) --> fires the existing load_skill() machinery
- skill must belong to a router pulled this turn
- context templates injected as system messages
- llm_visible code-block tools join the next tool assemblyFail toward deny. Every validation failure (unknown router, skill not in a pulled router, inactive skill, …) returns a typed error naming the reason plus a hard-stop directive, and every “could not validate” (pool down, read error) denies rather than loads. Enforcement is structural: domain tools do not exist in the run until select_skill succeeds.
Routers are an admin-curated recruitment taxonomy stored in agent-config-service (skill_routers, skill_router_map, skill_description_versions — migration 010; see Agent Config Service). Routers are soft-deactivated, never hard-deleted; router↔skill mappings carry a promotion status (draft / pending_review / approved / rejected — admin submissions auto-approve), and only approved mappings render. The seed creates two approved routers: spacing → rrc_rule37, and flaring → rrc_rule32 + flaring_watch — the flaring router carries a watch/file pair whose disambiguation descriptions draw the line (routine volume/emissions status → flaring_watch, exception-filing preparation → rrc_rule32). version_check_on_turn = true is set on the two rrc filing skills (not the read-only watch skill); the legacy rule37-spacing registry skill is intentionally unmapped. Description versions are append-only: the seed inserts a new approved version only when none exists or when the latest approved version is seed-authored (submitted_by IS NULL) and the seed text changed — it never supersedes an admin edit.
Live-conversation context rules. The index-0 system block is sealed at conversation birth (conversation_runtime_state) and reused byte-for-byte on reopen; all later change is tail-append only (conversation_context_appends): router changes arrive as appended delta notices (watermark = MAX(skill_routers.updated_at)), skill version upgrades are lazy (per-turn for version_check_on_turn = true, at router re-pull otherwise) with supersession notices, and deleted (is_active = false) skills are unloaded with a tombstone notice — their code-block tools hard-fail at invocation.
Legacy Injection Format
The injected content for a legacy registry skill is formatted as a structured system message:
=== Skill Activated: Spacing Calculation ===
## Description
Calculates the distance from a proposed well surface location to all
lease boundary lines and to every existing well within the regulatory
spacing radius.
## Steps
1. Retrieve the subject well location from the knowledge graph
2. Identify the lease boundaries and compute distance to each lease line
3. Find all wells on the same lease and compute well-to-well distances
4. Find all wells on adjacent leases within 1,200 ft
5. Determine if standard spacing is met or exception is required
6. Return a spacing summary table
## Requirements
- Well must have surface_location coordinates in the knowledge graph
- Lease must have boundary information or known distances
## Output Format
Spacing Summary:
- Distance to nearest lease line: X ft (PASS/FAIL vs 1,200 ft / 467 ft)
- Distance to nearest well (same lease): X ft (PASS/FAIL vs 467 ft)
- Distance to nearest well (offset lease): X ft
- Exception required: YES/NO
- Exception type: Regular / Density / No-objection
## Entity Context
Well: Mitchell Ranch 1H (API: 42-329-12345)
Status: active, Type: horizontal
Lease: Mitchell Ranch Lease
Field: Spraberry (Trend Area), District 08
Operator: Permian Basin Energy LLC (P-5: 683214)Legacy Skill Registry (retired)
The skills / skill_artifacts tier registry and the “Registered Skills” tables below
describe the retired legacy skill system (seed_skills.py, retired in R41 B0). They
are kept here to explain the tier vocabulary. Live skills, routers, rules, and
personas are now data in agent-config-service (skill_definitions, skill_routers,
skill_router_map, skill_description_versions, rule_definitions, …), and each
installed vertical’s skills are declared by its pack manifest. The Rule 37 / Rule 32
skill IDs shown are the first vertical’s content, not a platform fixture.
Skills were stored in the PostgreSQL skills table:
CREATE TABLE skills (
id VARCHAR(100) PRIMARY KEY,
name VARCHAR(200) NOT NULL,
tier1_manifest JSONB NOT NULL,
tier2_definition JSONB NOT NULL,
tier3_artifact_refs JSONB,
domain_tags VARCHAR(100)[],
status VARCHAR(20) DEFAULT 'active',
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);Artifacts are in a separate table:
CREATE TABLE skill_artifacts (
id VARCHAR(100) PRIMARY KEY,
skill_id VARCHAR(100) REFERENCES skills(id),
name VARCHAR(200) NOT NULL,
content TEXT NOT NULL,
content_hash VARCHAR(64) NOT NULL,
token_estimate INT,
created_at TIMESTAMPTZ DEFAULT NOW()
);Registered Skills
Rule 37 Skills
| ID | Name | Domain Tags | HITL Checkpoints |
|---|---|---|---|
spacing-calculation | Spacing Calculation | spacing, rule_37, drilling | — |
offset-well-analysis | Offset Well Analysis | spacing, rule_37 | — |
rule37-filing-assembly | Rule 37 Filing Assembly | spacing, rule_37, drilling | pre_filing |
good-cause-narrative | Good Cause Narrative | spacing, rule_37 | good_cause_review |
Rule 32 Skills
| ID | Name | Domain Tags | HITL Checkpoints |
|---|---|---|---|
flaring-volume-calc | Flaring Volume Calculation | flaring, rule_32, compliance | — |
gas-analysis | Gas Composition Analysis | flaring, rule_32 | — |
rule32-filing-assembly | Rule 32 Filing Assembly | flaring, rule_32 | pre_filing |
emissions-estimate | Emissions Estimate | flaring, rule_32, compliance | — |
Pack-declared skills and checklists
Each installed vertical’s skills and its checklist template are declared by the pack
manifest (packs/<name>/manifest.yaml), discovered at startup. The RRC vertical ships
five packs — rule_37, rule_32, form_pr, flaring_monitor, and epa_oooob.
The workflow-driven checklist steps (originally the R2 “checklist-item skills”) emit
structured SSE events such as DATA_TABLE_UPDATE, FORM_FIELD_UPDATE, and
ARTIFACT_GENERATED; see Event System.
Injection Ledger Deduplication
The injection ledger is a Redis Hash at skill:ledger:{conversation_id}:
skill:ledger:conv-001
"skill:spacing-calculation" -> "injected"
"skill:offset-well-analysis" -> "injected"Before injecting any skill, the loader calls ledger_check() to see if the key already exists. This prevents the same skill definition from being injected twice even if the LLM selects it multiple times.
The ledger can also be used to track entity context injections and other deduplicated content. The evict endpoint allows removing a ledger entry to force re-injection if the underlying data has changed.
Seeding
The legacy seed_skills.py script and its tier registry are retired (R41 B0).
Skill definitions, routers, rules, and personas now live in the
agent-config-service and are seeded through that service.