How a Message Routes Through Apogee

This page walks through what happens when you interact with an AI assistant that has Apogee connected. Every message follows the same path: constraint routing, skill discovery, skill execution, and optionally chain management and gate evaluation.

The Entry Point

You type a message in your IDE (Claude Code, Cursor, or any MCP-compatible host). Before the assistant does anything else, it calls Apogee’s route tool with your message.

Step 1: Constraint Routing

Every message is classified as read or write intent.

route(message="What functions call process_payment?")

Returns:

{
  "intent": "read",
  "confidence": 0.95,
  "constraint": "read",
  "constraint_changed": false,
  "matched_skill": {
    "workflow_id": "cpg.callers",
    "title": "Find Callers",
    "score": 0.82
  },
  "directive": "Read constraint active. You may read files, discuss, and generate design docs. Do not implement, commit, or run write-capable skills."
}

What happens: Apogee classifies your intent through four layers — force-commands, phrase matching, imperative detection, and a read-by-default fallback. The constraint determines which skills are available. In read mode, only discovery and analysis tools are eligible. In write mode, the full catalog unlocks.

The constraint is a behavioral gate, not a suggestion. When the assistant is in read mode, run_skill will reject write-mode skills.

When the constraint transitions: if you say something like “let’s implement that,” the confidence crosses the threshold (≥ 0.70) and the constraint shifts to write. The assistant acknowledges the transition.

If matched_skill has a score ≥ 0.50, the assistant offers it to you. If an active chain session exists, chain_context tells the assistant what step is current so it doesn’t lose track.

See apogee-mcp for the full route return schema.

Step 2: Skill Discovery

When you describe what you want to do, the assistant searches the skill catalog.

find_skill(query="review this pull request")

Returns:

{
  "results": [
    {
      "workflow_id": "task.review.pr_review",
      "title": "PR Review",
      "summary": "Review a pull request...",
      "kind": "task",
      "score": 0.91
    }
  ],
  "total_searched": 133
}

What happens: Apogee fuzzy-matches your intent against 100+ compiled skills. Results are filtered by the current constraint — if you’re in read mode, write-only skills are excluded. Skills are ranked by relevance score.

The assistant picks the best match and shows you what it found. You can accept, ask for alternatives, or refine your request.

See Skill Runtime for how skills are compiled and organized.

Step 3: Skill Execution

Once a skill is selected, the assistant executes it.

run_skill(workflow_id="task.review.pr_review")

Returns:

{
  "workflow_id": "task.review.pr_review",
  "title": "PR Review",
  "prompt_text": "You are reviewing a pull request...",
  "resolved_inputs": {
    "project_root": "/home/user/my-project",
    "branch": "feature-auth"
  },
  "expected_artifacts": ["review_report.md"],
  "next_workflow": null
}

What happens: Apogee prepares the skill’s prompt with project-specific context — repo root, branch, available artifacts. The assistant receives prompt_text and follows its instructions.

If the skill is part of a collection (like a multi-step workflow), next_workflow points to the next skill in the sequence.

If an active chain is running, Apogee verifies that this skill matches the current chain step. Mismatches are rejected — you can’t skip ahead or run the wrong skill.

When a read-mode skill is called while the constraint is read, it executes directly. When a write-mode skill is called in auto mode, the constraint auto-transitions to write and the skill proceeds. In force-read mode, write skills are blocked.

See apogee-mcp for the full run_skill return schema.

Step 4: Lifecycle Chains

For multi-step work — implementing a feature, porting code, running a release — skills compose into chains.

Defining a chain:

define_chain(
    chain_type="plan",
    feature_slug="auth-middleware"
)

Returns a chain_handle with ordered steps, each linked to a skill. Steps can have conditions (skip if a prior feature isn’t done), completion contracts (prove the work was done before advancing), and failure policies (retry, backtrack, or halt).

Starting execution:

execute_chain(
    action="start",
    chain_handle={"chain_id": "...", "spec_fingerprint": "..."}
)

Returns the session state with the first step ready:

{
  "session_id": "chain-a1b2c3d4e5f6",
  "mode": "running",
  "current_step_id": "plan-01",
  "steps": [
    {"id": "plan-01", "status": "ready"},
    {"id": "plan-02", "status": "pending"}
  ]
}

The assistant runs the skill for the current step, then reports the outcome:

execute_chain(
    action="report",
    session_id="chain-a1b2c3d4e5f6",
    outcome={"status": "passed"}
)

What happens: the chain executor verifies the completion contract (was the skill actually invoked? does the expected artifact exist?), then advances to the next step. If the outcome is failed, the failure policy determines what happens — retry the step, backtrack to an earlier step, or halt the chain.

Chains can be paused, resumed, checkpointed (saved to disk), and restored across sessions. Control commands include skip_step, backtrack, set_manual, abandon, and transfer (hand the chain to a different agent).

See Chain Engine for chain types, conditions, and control commands.

Step 5: Governance Gates

At lifecycle boundaries, Apogee evaluates governance gates against project policy.

# Read gate status via MCP resource
# apogee://status/gates

Returns:

{
  "status": "passed_with_warnings",
  "findings": [
    {
      "code": "stale_manifest",
      "severity": "warning",
      "message": "Manifest is older than 7 days"
    }
  ],
  "policy_name": "default"
}

What happens: the gate evaluator checks conditions defined in apogee.policy.json — stale manifests, missing CI reports, failed proof reports, invalid checkpoints. Each condition maps to a severity level (blocker, warning, acceptable, informational). Any blocker-severity finding blocks the gate.

Lifecycle stage affects defaults: a pre-release project treats missing proof reports as acceptable, while a released project treats them as warnings.

Gates are an inspection endpoint, not an inline chain step. The assistant checks gates when the workflow calls for it — typically before a release or at tier boundaries.

See Gate System for severity levels, conditions, and immutable gates.

Step 6: Structural Analysis

Throughout any workflow, the assistant can query Apogee’s Code Property Graph for structural evidence.

cpg_impact_analysis(
    function_name="process_payment",
    file="src/billing/checkout.py"
)

The CPG engine provides call graphs, security scanning, branch divergence, backport safety checks, and temporal diffs — all queryable without executing target code. These tools inform decisions at every stage: “is this function safe to change?” during implementation, “what diverged?” during review, “are there security regressions?” before release.

See CPG Engine for the full tool reference.

Worked Example

Here’s a complete flow for implementing a feature:

  1. You: “I want to add rate limiting to the API endpoints”

  2. Route: classifies as write intent → constraint transitions to write, matched skill feature.single_spec at 0.85

  3. Find skill: confirms feature.single_spec — generates a design doc and example for the feature

  4. Run skill: returns a prompt that guides the assistant through writing design.md and example.md in apogee_artifacts/features/rate-limiting/

  5. Define chain: define_chain(chain_type="plan", feature_slug="rate-limiting") derives ordered implementation steps from the plan prompts

  6. Execute chain: starts at step 1, the assistant runs each plan skill, reports outcomes. If a step fails, the failure policy determines retry or backtrack.

  7. Gate check: after the last plan, the assistant checks gates — manifest freshness, test results, proof report status

  8. Commit: the assistant uses the commit workflow skill with proper attribution trailers

At each step, you’re in control. Chains can be paused, plans can be revised, and the constraint router prevents accidental writes during exploration.

Variations

Read-only query (no chain, no gate): message → route (read) → find_skillrun_skill (e.g., cpg_impact_analysis) → result. Fast path, no state changes.

Single skill (no chain): message → route (write) → find_skillrun_skill (e.g., task.git.commit_feature) → done. One skill, one outcome.

Full chain (multi-step): message → routedefine_chainexecute_chain (start) → repeat (run_skillreport) per step → gate check → done.

See Also