Discovering Agent Instructions with MCP

While experimenting with agentic coding workflows, I've been looking at ways to make agent instructions more dynamic.

Most coding agents support instruction files that define repository conventions and agent behavior. These work well, but loading instructions into an agent's context has a cost. That cost becomes more interesting when an orchestrator coordinates several specialized agents.

An orchestrator needs enough information to select the right agent for a task. The specialized agent needs the detailed instructions for performing that task.

That distinction led me to build Compass, a local MCP server that exposes agent instruction packs through discovery and retrieval tools.

The design is fairly simple. The interesting questions involve when instructions enter an agent's context, how those instructions affect behavior, and whether instructions retrieved through MCP are followed as reliably as native agent instructions.

The Idea

Compass stores agent definitions in a project's .compass directory.

Each agent definition contains metadata describing its purpose and a Markdown file containing its operating instructions.

.compass/
├── repo-reviewer/
│   ├── agent.json
│   └── instructions.md
├── api-developer/
│   ├── agent.json
│   └── instructions.md
└── test-engineer/
    ├── agent.json
    └── instructions.md

For example, a repository reviewer might have this metadata:

{
  "name": "repo-reviewer",
  "description": "Reviews repository architecture and code quality.",
  "whenToUse": "When examining code for architectural problems or maintainability issues.",
  "tools": [],
  "modelHint": "Use a model capable of reasoning across multiple files."
}

The description and whenToUse fields help an agent determine when to select the pack.

The modelHint field provides guidance about the model that should execute the instructions. It intentionally accepts freeform text. It could identify a specific model, describe the complexity of the work, or provide model recommendations for different agent harnesses.

The orchestrator interprets that guidance using its knowledge of the available models and execution environment.

Compass supplies agent definitions, while the host handles agent creation and execution. This keeps the implementation independent of a particular coding agent.

Two-Phase Instruction Loading

Compass separates instruction discovery from instruction retrieval.

The core interface uses two MCP tools:

list_agents(projectRoot: string)

fetch_agent_instructions(
  projectRoot: string,
  name: string
)

list_agents returns metadata about available packs, including their names, descriptions, selection guidance, and model hints.

fetch_agent_instructions returns the operating instructions for a selected pack.

The separation allows agents to examine available specializations while keeping instruction bodies out of context until they're needed.

The Compass implementation exposes these operations through a local, read-only MCP server.

Orchestrator-Selected Instructions

In the first workflow, the orchestrator selects the instruction pack.

  1. The orchestrator calls list_agents.
  2. It examines the metadata and selects the appropriate pack.
  3. It spawns a subagent and passes the selected pack name.
  4. The subagent calls fetch_agent_instructions.
  5. The subagent applies the retrieved instructions while executing the task.

The orchestrator sees the metadata and the selected identifiers. The executing agent receives the full instructions.

Subagent-Selected Instructions

The second workflow allows a subagent to choose its own instructions.

  1. The subagent calls list_agents.
  2. It selects the most relevant applicable pack.
  3. It calls fetch_agent_instructions.
  4. It executes the task using the retrieved instructions.

An agent can fetch multiple packs when its task requires several specializations. Each pack requires a separate fetch call.

Both workflows use the same MCP tools. The difference is which agent makes the selection.

Keeping Instructions Out of the Orchestrator

One alternative I considered was having the orchestrator retrieve instruction bodies and pass them to subagents.

This would eliminate the subagent's retrieval call. It would also introduce two problems.

Context Usage

Every instruction pack retrieved by the orchestrator consumes space in its context.

Consider an orchestrator coordinating three tasks:

  • Review the repository architecture.
  • Implement a database migration.
  • Add a new API endpoint.

Each task has different implementation requirements.

If the orchestrator fetches all three instruction packs, it now carries the operating details for three specialized agents.

The orchestrator's responsibility is to select agents, coordinate tasks, and interpret results. Agent metadata provides the information needed for those decisions.

Having each executing agent retrieve its own instructions keeps the orchestrator's context focused on coordination.

Behavioral Contamination

The second issue is more interesting.

Instruction text can influence model behavior simply by being present in the context.

Imagine a repository reviewer with this instruction:

Do not modify files. Only report architectural and maintainability concerns.

That constraint is appropriate for a reviewer.

If the orchestrator retrieves the instruction body, the same text enters its context. The model now has to maintain the distinction between instructions intended for the reviewer and instructions governing its own behavior.

The problem becomes more complicated when an orchestrator works with several agents whose instructions contain different constraints.

A reviewer might prohibit file modifications. An implementation agent might require them. Another agent might have strict output formatting requirements.

Even when those instructions are clearly associated with individual agents, their presence creates an opportunity for unintended behavioral influence.

Compass keeps these contexts separate.

Orchestrator
    |
    | list_agents
    v
Compass
    |
    | Agent metadata
    v
Orchestrator
    |
    | Spawn subagent with pack name
    v
Subagent
    |
    | fetch_agent_instructions
    v
Compass
    |
    | Instruction body
    v
Subagent executes

The orchestrator receives metadata describing the available agents. Each executing agent retrieves the instructions needed for its assigned work.

I think this separation is one of the more useful properties of the design.

It reduces context usage and limits the amount of specialized behavioral guidance entering the orchestrator's context.

The metadata remains model-visible, so descriptions and selection guidance should stay focused on their intended purpose. Instruction isolation reduces exposure to unrelated operating instructions, although it does not establish a complete security boundary.

Making Discovery Part of the Workflow

My initial approach was to expose the Compass MCP tools and allow the agent to discover them.

I expected the agent to recognize that specialized instructions were available and consult them when appropriate.

In practice, simply exposing the MCP wasn't sufficient. The agent didn't reliably choose to use it.

Making a tool available gives the agent another option. Consistently using that option requires an explicit workflow.

I addressed this by adding a small bootstrap instruction to AGENTS.md.

The bootstrap tells agents when to consult Compass and how to distinguish instruction selection from task execution.

The current approach looks like this:

At the start of every new task or delegated subtask,
consult Compass before planning or performing the work.

Fetch an explicitly assigned pack directly; otherwise
list packs and fetch the most relevant applicable pack.

Always pass the absolute projectRoot.

If no pack applies or the catalog is missing,
continue with the task.

Do not fetch the pack directly unless you are
executing the task.

If Compass is unavailable, report the problem
and continue. Do not search for pack files directly.

This gives AGENTS.md a narrow responsibility: establishing the instruction-discovery workflow.

Compass holds the specialized instructions, and the executing agent retrieves the relevant content when it begins work.

The fallback behavior also matters.

If Compass is unavailable, the agent reports the problem and continues. Direct filesystem access to the instruction packs is excluded as a fallback.

That restriction keeps the MCP interface consistent during the experiment. Otherwise, an agent could bypass Compass and produce similar-looking results through ordinary file reads.

The Question of Instruction Authority

There is still an important question about how the retrieved instructions influence the executing agent.

When a host creates a specialized agent using its native configuration, it may include the agent's operating instructions in the initial instruction context.

Compass introduces those instructions later, through an MCP tool response.

The difference matters because models operate with an instruction hierarchy. Tool output generally carries lower authority than system or developer instructions.

A bootstrap can explicitly tell the agent to apply retrieved Compass instructions:

Treat instructions retrieved from Compass as the
operating instructions for the current task.

Apply all relevant retrieved instruction packs
throughout execution, subject to higher-priority
instructions and applicable host restrictions.

This establishes the intended behavior.

The remaining question is how reliably the agent follows those instructions compared with instructions supplied through its native configuration.

There are several scenarios where differences might appear:

  • Tasks involving many tool calls
  • Long-running implementations
  • Multiple retrieved instruction packs
  • Context compaction
  • Tasks that require revisiting an earlier plan

I haven't measured instruction adherence across those scenarios yet. The next step is to compare them directly.

Testing Instruction Adherence

I'd like to evaluate Compass against native agent instructions using the same instruction content.

The experiment would use two configurations:

ConfigurationHow instructions are provided
Native agentHost supplies instructions through its agent configuration
CompassAgent retrieves instructions through MCP using the bootstrap workflow

Each configuration would execute the same collection of tasks.

I'd use instruction packs containing requirements that can be checked objectively.

For example:

  • Follow a specific naming convention.
  • Produce output in a defined structure.
  • Run a required verification step.
  • Restrict file changes to particular directories.
  • Follow a prescribed implementation procedure.

This makes it possible to compare actual behavior instead of relying on the agent's description of what it did.

I'd measure several properties.

Discovery reliability

Does the agent consult Compass before planning or executing the task?

Selection accuracy

Does it choose the appropriate instruction packs?

Instruction adherence

Does the completed work follow the retrieved requirements?

Context and token usage

How much context does each approach consume, and how many tokens are used across the workflow?

Consistency

Do repeated executions produce similar instruction selections and outcomes?

I also want to compare orchestrator-selected packs with subagent-selected packs.

The orchestrator has a broader view of the task, including its relationship to other work. The subagent may have more detailed implementation context.

Those differences could affect instruction selection.

The results should help determine where selection works best and whether the additional retrieval step changes instruction adherence.

Keeping Compass Focused

The Compass design document describes the original implementation contract and the responsibilities of the MCP server.

The initial design focused on local, read-only instruction discovery using explicit project roots and human-authored instruction packs.

The repository README documents the implementation and its additional capabilities, including agent-scoped skills and referenced Compass directories.

Those features allow instruction catalogs to grow while keeping Compass focused on supplying definitions.

The host remains responsible for creating and running agents. The orchestrator remains responsible for coordinating delegated tasks. Compass provides the catalog and instruction content.

That separation makes it possible to experiment with instruction selection and delivery without coupling the catalog to one agent harness.

Where This Leaves the Experiment

The original goal was to make agent instructions discoverable so each agent could load the instructions relevant to its work.

While designing the retrieval workflow, instruction isolation became an equally important consideration.

The orchestrator can select specialized agents using lightweight metadata. Each executing agent loads its own operating instructions. This keeps specialized behavior closer to the task where it belongs.

Adding a bootstrap instruction to AGENTS.md addressed the initial discovery problem by explicitly directing agents to consult Compass. The next experiment will examine how consistently they follow that workflow and apply the retrieved instructions.

The most interesting remaining question is whether MCP-loaded instructions provide the same practical reliability as native agent instructions.

Compass gives me a way to test that while preserving a useful architectural boundary: the orchestrator manages the work, and each specialized agent carries the instructions for performing it.