Skip to content
Regolo Logo
Tutorial & How‑to

Context engineering for agents 101 (part 1): progressive skill disclosure and concise tools

Preloading 10 full SKILL.md manuals and 8 raw GitHub REST API issues bills 53,452 prompt tokens (7.63s) on Turn 1. See how our 1-line progressive skill menu and concise MCP tools cut Turn 1 on Qwen3.8-27B to 1,019 tokens (-98.09%, 0.79s).

Alex Genovese
18 min read
Share

When a coding agent loses track of your instructions around turn twenty, the instinct is to blame the model checkpoint and reach for a larger parameter count. In practice, most mid-session failures happen before the model even starts reasoning: the agent harness has quietly filled the context window with thirty thousand tokens of unused skill manuals, verbose MCP schemas, and raw database UUIDs.

Even when you run long-context open-weight models like GLM-5.2 or Qwen3.8-27B on our API, treating a large context window like an infinite hard drive degrades recall and drives up latency on every turn. Research teams at Anthropic Engineering, LangChain, and Chroma Research call this effect context rot: every unnecessary token in the window competes for the model’s attention budget.

How do you give daily coding agents like OpenCode, Claude Code, and Codex access to dozens of specialized skills and tools without paying a forty-thousand-token startup tax on every turn?

In Part 1 of our Context Engineering for Agents 101 series, we build, test, and validate our first drop-in harness module (piece1_progressive_skills.py). It adds two core primitives to your agent loop: progressive skill disclosure and concise tool response formatting, backed by a local MCP server you can wire into OpenCode, Claude Code, and Codex in under a minute.

Quick summary (TL;DR): Preloading 10 full SKILL.md manuals and 8 raw GitHub REST API issue objects at startup bills 53,452 prompt tokens (7.63s latency) on qwen3.8-27b before your coding agent reads a single repository file. Replacing eager loading with a one-line progressive skill menu (35,685 → 293 prompt tokens, -99.18%) and concise tool formatting (17,794 → 753 prompt tokens, -95.77%) cuts total Turn-1 prompt usage by 98.09% (53,452 → 1,019 tokens in 0.79s) and keeps Turn 2 at 3,996 tokens (-92.52%) when loading a needed skill on demand across OpenCode, Claude Code, Codex, and Roo Code on our European API.

TURN-1 CONTEXT WINDOW ANATOMY · PIECE 1 REAL API BENCHMARK

What actually enters your model’s context window on Turn 1?

Comparing a naive coding agent (preloading 10 full SKILL.md manuals + 8 raw open issues from modelcontextprotocol/python-sdk via the GitHub REST API) against Piece 1 (1-line progressive menu + on-demand MCP loading + concise tool output) measured on qwen3.8-27b.

BEFORE · NAIVE EAGER PRELOAD + RAW GITHUB JSON
All 10 skill manuals & 8 raw GitHub issue payloads dumped at Turn 1
53,452 prompt tokens billed on Turn 1 (7.63s)
10 full SKILL.md files preloaded: 35,685 tok (66.8%) — 9 of 10 unused!
8 raw GitHub issues: 17,794 tok (33.2%)
1. System prompt bloat (35,685 prompt_tokens)
# Skill: ab-testing (12,525 chars) Full experiment checklists, ICE scoring tables... # Skill: ad-creative, ads, ai-evals, ai-seo... [+ 9 more full SKILL.md files preloaded at Turn 1]
2. Raw GitHub API JSON (17,794 prompt_tokens / 8 issues)
{"id": 3918273641, "node_id": "I_kwDOM...", "user": {"avatar_url": "https://avatars.githubusercontent.com/...", "followers_url": "https://api.github.com/users/..."}, "title": "Issue #3804...", "state": "open", "body": "..."}
AFTER · PIECE 1 PROGRESSIVE DISCLOSURE + CONCISE TOOLS
1-line skill index + on-demand MCP fetch + concise GitHub issue output
1,019 prompt tokens billed on Turn 1 (-98.09%, 0.79s)
52,433 tokens of startup & JSON noise eliminated — 98.09% of attention budget preserved (3,996 tok / -92.52% on Turn 2 with 1 skill loaded)
1. Compact 1-line index (293 prompt_tokens, -99.18%)
Available on-demand skills (call load_skill(name) only when needed): - ab-testing: When the user wants to plan, design, or implement... - ai-evals: Help users build robust infrastructure for measuring... → Loading 1 full skill on demand at Turn 2 uses 3,996 tok (-92.52%)
2. Concise GitHub output (753 prompt_tokens, -95.77%)
[{"number":3804,"title":"...","status":"open","owner":"...", "labels":["bug"],"summary":"First 160 chars of issue body..."}] → Zero node_ids, follower URLs, or avatar URLs in context
35,685 → 293 tok startup skill prompt tokens (-99.18%) measured on qwen3.8-27b across 10 real local SKILL.md files
17,794 → 753 tok tool payload tokens (-95.77%) on 8 real open issues from modelcontextprotocol/python-sdk
1,019 tok (0.79s) total Turn-1 prompt (-98.09% vs 53,452 tok in 7.63s), and 3,996 tok (-92.52%) when loading 1 skill on Turn 2

Measured via live usage.prompt_tokens on https://api.regolo.ai/v1 (qwen3.8-27b, enable_thinking=False, November 2, 2026) and GitHub REST API (modelcontextprotocol/python-sdk).

The real numbers on Qwen3.8-27B: 10 local skills and 8 live GitHub REST API issues

Rather than relying on character-division heuristics or synthetic mock records, we measured every stage of Piece 1 directly against the server tokenizer on https://api.regolo.ai/v1 (model="qwen3.8-27b", enable_thinking=False) using 10 real local SKILL.md manuals and 8 real open issues fetched live from modelcontextprotocol/python-sdk via the GitHub REST API:

Measured prompt tokens and wall-clock latency on Qwen3.8-27B

Every row below records real usage.prompt_tokens and latency from https://api.regolo.ai/v1/chat/completions (November 2, 2026).

100% Real API Tokenizer + Live GitHub JSON
Benchmark Stage Naive BaselineEager preload + raw JSON Piece 1 Harness1-line menu + concise JSON Measured Reductionusage.prompt_tokens Latency Impactqwen3.8-27b (EU API)
1. Startup skill prefix10 local ~/.claude/skills/*/SKILL.md files 35,685 tok9 of 10 skills unused on task 293 tok1-line name + summary index -99.18%35,392 tokens saved at boot 4.03s → 0.33s12.2x faster prefix prefill
2. External tool output8 open issues from modelcontextprotocol/python-sdk 17,794 tok58,913 chars of raw GitHub JSON 753 tok2,863 chars (concise mode) -95.77%Strips avatar_url, node_id, URLs Identical answer8 issues (#3804 first)
3. Combined Turn 110 skills + 8 GitHub issues + user question 53,452 tokOver 53k tokens on Turn 1 1,019 tok98.09% of window stays free -98.09%52,433 tokens eliminated 7.63s → 0.79s9.6x faster Turn-1 response
4. Turn 2 on-demand loadAgent calls load_skill_on_demand(“ab-testing”) 53,452 tokPays for all 10 skills every turn 3,996 tokLoads only the 1 needed skill -92.52%Even after loading a 12.5KB skill 7.63s → 0.87sFull skill instructions intact
SOVEREIGN EUROPEAN INFERENCE
Run OpenCode, Claude Code, and Codex on our EU open-weight API

Get 600 million monthly tokens across GLM-5.2, Qwen3.8-27B, Qwen3.5-122B, GPT-OSS 120B, Qwen3-Embedding-8B, and Brick on our flat Core plan (€39/mo, ~€0.065/1M) with certified Zero Data Retention.

Start 30-day free trial (no card required) →

Free credits included · 100% green energy · ✓ EU Green Datacenters   ✓ Certified ZDR

Two harness primitives: progressive skill menus and concise tool responses

As highlighted in LangChain’s Deep Agents guide and Anthropic’s tool engineering research, keeping irrelevant tokens out of the window starts with two structural changes in your harness:

  1. Progressive disclosure for skills: Instead of injecting the full body of every SKILL.md file into the system prompt, scan your skills folder at startup and extract only the skill name and its first-sentence description. Ten skills occupy 293 prompt tokens on qwen3.8-27b instead of 35,685 tokens (-99.18%). When the agent encounters a task that matches a skill, it calls load_skill_on_demand(skill_name) to pull the full instructions just in time (bringing Turn 2 to 3,996 prompt tokens, still 92.52% smaller than preloading all ten manuals).
  2. A response_format toggle on every tool: Add an enum parameter ("concise" vs "detailed") to your custom tools. Default to "concise" so daily searches return issue numbers, titles, statuses, labels, and a 160-character summary without avatar URLs, GraphQL node_id strings, or nested API URLs (cutting 8 real GitHub issue records from 17,794 prompt tokens down to 753 prompt tokens, -95.77%).
MEASURED HARNESS SAVINGS · PIECE 1 REAL API BENCHMARK

Real prompt tokens billed on Qwen3.8-27B before vs after

Measured across 10 local SKILL.md files and 8 live open issues from modelcontextprotocol/python-sdk.

Naive Turn 153,452 tok
Piece 1 Turn 11,019 tok
Full 10 skills35,685 tok
1-line menu293 tok
Raw GitHub17,794 tok
Concise JSON753 tok
Turn 2 (1 skill)3,996 tok

Verified via python3 piece1_progressive_skills.py --self-test on https://api.regolo.ai/v1 (qwen3.8-27b, Nov 2, 2026).

Build, test, and validate Piece 1 in Python (copy-paste & run)

Save the complete script below as piece1_progressive_skills.py (also available in our context-engineering-101 GitHub kit). It uses zero character-division estimates and zero synthetic data: when you run --self-test, it scans your local skills folder, fetches 8 real open issues from https://api.github.com/repos/modelcontextprotocol/python-sdk/issues, and measures the exact usage.prompt_tokens and wall-clock latency on https://api.regolo.ai/v1 (qwen3.8-27b with "chat_template_kwargs": {"enable_thinking": False} so routine harness turns complete in under a second):

#!/usr/bin/env python3
"""
piece1_progressive_skills.py: Progressive skill menu + concise tool formatter.
Run `python3 piece1_progressive_skills.py --self-test` with REGOLO_API_KEY to verify
real usage.prompt_tokens and latency on https://api.regolo.ai/v1 (qwen3.8-27b) + GitHub REST API.
"""
from __future__ import annotations
import argparse, json, os, re, ssl, time, urllib.request
from pathlib import Path
from typing import Any, Dict, List

REGOLO_BASE_URL = os.environ.get("REGOLO_BASE_URL", "https://api.regolo.ai/v1")
MODEL = os.environ.get("REGOLO_MODEL", "qwen3.8-27b")
_SSL_CTX = ssl._create_unverified_context()


class ProgressiveSkillRegistry:
    """Loads only name + 1-line description at startup; reads full SKILL.md on demand."""

    def __init__(self, skills_dir: Path, max_skills: int = 10) -> None:
        self.skills_dir = Path(skills_dir).expanduser()
        self.max_skills = max_skills
        self._index: Dict[str, Dict[str, str]] = {}
        if self.skills_dir.exists():
            for skill_md in sorted(self.skills_dir.glob("*/SKILL.md"))[: self.max_skills]:
                raw = skill_md.read_text(encoding="utf-8", errors="ignore")
                m = re.search(r"description:\s*(.+)", raw)
                desc = m.group(1).strip().strip("'\"") if m else "On-demand agent skill."
                summary = re.split(r"(?<=[.!?])\s+", desc)[0][:110]
                self._index[skill_md.parent.name] = {"path": str(skill_md), "summary": summary}

    def compact_menu(self) -> str:
        lines = ["Available on-demand skills (call load_skill(name) only when needed):"]
        return "\n".join(lines + [f"- {k}: {v['summary']}" for k, v in self._index.items()])

    build_compact_menu = compact_menu

    def full_preload_text(self) -> str:
        return "\n\n".join(
            Path(meta["path"]).read_text(encoding="utf-8", errors="ignore")
            for meta in self._index.values()
        )

    def load_skill(self, name: str) -> str:
        if name not in self._index:
            return f"Skill '{name}' not found. Available: {', '.join(self._index)}."
        return Path(self._index[name]["path"]).read_text(encoding="utf-8", errors="ignore")


def format_tool_response(records: List[Dict[str, Any]], response_format: str = "concise") -> str:
    if response_format == "detailed":
        return json.dumps(records, indent=2)
    concise_rows = []
    for r in records:
        row: Dict[str, Any] = {}
        if "number" in r:
            row["number"] = r["number"]
        if "title" in r:
            row["title"] = r["title"]
        if "status" in r or "state" in r:
            row["status"] = r.get("status") or r.get("state")
        if "owner" in r:
            row["owner"] = r["owner"]
        elif isinstance(r.get("user"), dict) and "login" in r["user"]:
            row["owner"] = r["user"]["login"]
        if isinstance(r.get("labels"), list):
            row["labels"] = [lbl.get("name") if isinstance(lbl, dict) else str(lbl) for lbl in r["labels"]]
        if "summary" in r:
            row["summary"] = r["summary"]
        elif "body" in r and r["body"]:
            row["summary"] = re.sub(r"\s+", " ", str(r["body"]).strip())[:160]
        concise_rows.append(row)
    return json.dumps(concise_rows, separators=(",", ":"))


def fetch_real_github_issues(repo: str = "modelcontextprotocol/python-sdk", count: int = 8) -> List[Dict[str, Any]]:
    req = urllib.request.Request(
        f"https://api.github.com/repos/{repo}/issues?state=open&per_page=20",
        headers={"Accept": "application/vnd.github+json", "User-Agent": "regolo-context-101/1.0"},
    )
    with urllib.request.urlopen(req, timeout=30, context=_SSL_CTX) as resp:
        items = json.loads(resp.read().decode("utf-8"))
    pure = [it for it in items if "pull_request" not in it]
    return (pure if len(pure) >= count else items)[:count]


def measure_on_regolo_api(api_key: str, messages: List[Dict[str, str]], max_tokens: int = 80) -> Dict[str, Any]:
    t0 = time.perf_counter()
    body = json.dumps({
        "model": MODEL,
        "messages": messages,
        "max_tokens": max_tokens,
        "temperature": 0.0,
        "chat_template_kwargs": {"enable_thinking": False},
    }).encode("utf-8")
    req = urllib.request.Request(
        f"{REGOLO_BASE_URL}/chat/completions",
        data=body,
        headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
        method="POST",
    )
    with urllib.request.urlopen(req, timeout=90, context=_SSL_CTX) as resp:
        data = json.loads(resp.read().decode("utf-8"))
    return {
        "prompt_tokens": data.get("usage", {}).get("prompt_tokens"),
        "latency_s": round(time.perf_counter() - t0, 2),
        "reply": (data["choices"][0]["message"].get("content") or "").strip(),
    }


def run_self_test() -> Dict[str, Any]:
    api_key = os.environ.get("REGOLO_API_KEY", "").strip()
    if not api_key:
        raise RuntimeError("Export REGOLO_API_KEY before running --self-test")
    skills_path = Path("~/.claude/skills").expanduser()
    if not skills_path.exists():
        skills_path = Path("~/.agents/skills").expanduser()
    reg = ProgressiveSkillRegistry(skills_path, max_skills=10)
    full_skills, menu = reg.full_preload_text(), reg.compact_menu()
    gh_issues = fetch_real_github_issues("modelcontextprotocol/python-sdk", count=8)
    detailed_str, concise_str = format_tool_response(gh_issues, "detailed"), format_tool_response(gh_issues, "concise")

    skill_full = measure_on_regolo_api(api_key, [{"role": "system", "content": full_skills}, {"role": "user", "content": "Reply with OK."}], 8)
    skill_menu = measure_on_regolo_api(api_key, [{"role": "system", "content": menu}, {"role": "user", "content": "Reply with OK."}], 8)
    q = "Reply in one sentence naming how many open issues are in this list and the number of the first issue."
    tool_det = measure_on_regolo_api(api_key, [{"role": "system", "content": "You are a coding assistant."}, {"role": "user", "content": f"Here is the GitHub issue list:\n{detailed_str}\n{q}"}])
    tool_con = measure_on_regolo_api(api_key, [{"role": "system", "content": "You are a coding assistant."}, {"role": "user", "content": f"Here is the GitHub issue list:\n{concise_str}\n{q}"}])
    t1_unfiltered = measure_on_regolo_api(api_key, [{"role": "system", "content": full_skills}, {"role": "user", "content": f"Here is the GitHub issue list:\n{detailed_str}\n{q}"}])
    t1_piece1 = measure_on_regolo_api(api_key, [{"role": "system", "content": menu}, {"role": "user", "content": f"Here is the GitHub issue list:\n{concise_str}\n{q}"}])
    first_skill = next(iter(reg._index))
    t2_ondemand = measure_on_regolo_api(api_key, [{"role": "system", "content": menu}, {"role": "user", "content": f"[Tool result from load_skill_on_demand('{first_skill}')]:\n{reg.load_skill(first_skill)}\n\nHere is the concise GitHub issue list:\n{concise_str}\nReply in one sentence naming how many open issues are in this list."}])

    res = {
        "model": MODEL,
        "skills_scanned": len(reg._index),
        "skill_full_preload_prompt_tokens": skill_full["prompt_tokens"],
        "skill_compact_menu_prompt_tokens": skill_menu["prompt_tokens"],
        "skill_prefix_reduction_pct": round((1 - skill_menu["prompt_tokens"] / skill_full["prompt_tokens"]) * 100, 2),
        "tool_detailed_prompt_tokens": tool_det["prompt_tokens"],
        "tool_concise_prompt_tokens": tool_con["prompt_tokens"],
        "tool_response_reduction_pct": round((1 - tool_con["prompt_tokens"] / tool_det["prompt_tokens"]) * 100, 2),
        "turn1_unfiltered_prompt_tokens": t1_unfiltered["prompt_tokens"],
        "turn1_unfiltered_latency_s": t1_unfiltered["latency_s"],
        "turn1_piece1_prompt_tokens": t1_piece1["prompt_tokens"],
        "turn1_piece1_latency_s": t1_piece1["latency_s"],
        "turn1_total_reduction_pct": round((1 - t1_piece1["prompt_tokens"] / t1_unfiltered["prompt_tokens"]) * 100, 2),
        "turn1_reply": t1_piece1["reply"],
        "turn2_on_demand_skill_loaded": first_skill,
        "turn2_on_demand_prompt_tokens": t2_ondemand["prompt_tokens"],
        "turn2_vs_unfiltered_reduction_pct": round((1 - t2_ondemand["prompt_tokens"] / t1_unfiltered["prompt_tokens"]) * 100, 2),
    }
    print(json.dumps(res, indent=2))
    return res


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--self-test", action="store_true")
    parser.parse_args()
    run_self_test()
Code language: Python (python)

Run the built-in validation check against our API to reproduce every measurement with your own eyes:

export REGOLO_API_KEY="your-regolo-api-key"
python3 piece1_progressive_skills.py --self-test
# Measured output on https://api.regolo.ai/v1 (qwen3.8-27b):
# {
#   "model": "qwen3.8-27b",
#   "skills_scanned": 10,
#   "skill_full_preload_prompt_tokens": 35685,
#   "skill_compact_menu_prompt_tokens": 293,
#   "skill_prefix_reduction_pct": 99.18,
#   "tool_detailed_prompt_tokens": 17794,
#   "tool_concise_prompt_tokens": 753,
#   "tool_response_reduction_pct": 95.77,
#   "turn1_unfiltered_prompt_tokens": 53452,
#   "turn1_unfiltered_latency_s": 7.63,
#   "turn1_piece1_prompt_tokens": 1019,
#   "turn1_piece1_latency_s": 0.79,
#   "turn1_total_reduction_pct": 98.09,
#   "turn1_reply": "There are 8 open issues in this list, and the number of the first issue is 3804.",
#   "turn2_on_demand_skill_loaded": "ab-testing",
#   "turn2_on_demand_prompt_tokens": 3996,
#   "turn2_vs_unfiltered_reduction_pct": 92.52
# }
Code language: Bash (bash)
ZERO DATA RETENTION
Get engineering notes and model releases in your inbox.

Sovereign AI inference, OpenAI-compatible, EU-hosted. Benchmarks, new models (Mistral, Qwen, GLM), and cost insights. One email, no spam.

✓
Thank you for subscribing!

Please check your inbox to confirm your subscription.

100% European infrastructure · Zero spam · Unsubscribe anytime.

Plug Piece 1 into OpenCode, Claude Code, and Codex (step-by-step setup)

In Section 3 we created piece1_progressive_skills.py. To expose those functions to OpenCode, Claude Code, and Codex CLI, we now create a lightweight Model Context Protocol (MCP) server file in the same folder and register it in each agent’s configuration file. Follow the five steps below in order.

Step 1: Create the MCP server file (regolo_harness_mcp.py)

In the same folder where you saved piece1_progressive_skills.py, create a new file named regolo_harness_mcp.py and paste the code below. It uses only the Python standard library to speak JSON-RPC 2.0 over stdin/stdout, importing ProgressiveSkillRegistry and format_tool_response from piece1_progressive_skills.py and exposing them as two callable MCP tools (load_skill_on_demand and format_concise_tool_output):

#!/usr/bin/env python3
"""regolo_harness_mcp.py: MCP stdio server for OpenCode, Claude Code, and Codex CLI."""
from __future__ import annotations
import json, os, sys
from pathlib import Path
from piece1_progressive_skills import ProgressiveSkillRegistry, format_tool_response

SKILLS_DIR = Path(os.environ.get("REGOLO_SKILLS_DIR", "~/.claude/skills")).expanduser()

TOOLS = [
    {
        "name": "load_skill_on_demand",
        "description": "Load instructions for a named skill only when the current task requires it (progressive disclosure).",
        "inputSchema": {
            "type": "object",
            "properties": {
                "skill_name": {"type": "string", "description": "Exact skill folder name from the AGENTS.md menu."},
                "response_format": {"type": "string", "enum": ["concise", "detailed"], "default": "concise"}
            },
            "required": ["skill_name"]
        }
    },
    {
        "name": "format_concise_tool_output",
        "description": "Strip low-signal metadata (UUIDs, SHA hashes, raw stack traces) from a JSON tool payload.",
        "inputSchema": {
            "type": "object",
            "properties": {
                "raw_json": {"type": "string", "description": "Raw JSON string returned by an external tool."},
                "response_format": {"type": "string", "enum": ["concise", "detailed"], "default": "concise"}
            },
            "required": ["raw_json"]
        }
    }
]

def handle_rpc(req: dict) -> dict | None:
    method, req_id = req.get("method"), req.get("id")
    if method == "initialize":
        return {
            "jsonrpc": "2.0",
            "id": req_id,
            "result": {
                "protocolVersion": "2024-11-05",
                "capabilities": {"tools": {}},
                "serverInfo": {"name": "regolo-context-harness", "version": "1.0.0"}
            }
        }
    if method == "tools/list":
        return {"jsonrpc": "2.0", "id": req_id, "result": {"tools": TOOLS}}
    if method == "tools/call":
        params = req.get("params", {})
        name, args = params.get("name"), params.get("arguments", {})
        if name == "load_skill_on_demand":
            registry = ProgressiveSkillRegistry(SKILLS_DIR)
            text = registry.load_skill(args["skill_name"])
            if args.get("response_format", "concise") == "concise":
                text = "\n".join(text.splitlines()[:40])
        elif name == "format_concise_tool_output":
            payload = json.loads(args["raw_json"])
            text = format_tool_response(payload, response_format=args.get("response_format", "concise"))
        else:
            text = f"Unknown tool: {name}"
        return {"jsonrpc": "2.0", "id": req_id, "result": {"content": [{"type": "text", "text": text}]}}
    return None

if __name__ == "__main__":
    if "--self-test" in sys.argv:
        init_ok = handle_rpc({"jsonrpc": "2.0", "id": 1, "method": "initialize"})
        list_ok = handle_rpc({"jsonrpc": "2.0", "id": 2, "method": "tools/list"})
        assert init_ok and list_ok and len(list_ok["result"]["tools"]) == 2
        print("MCP stdio handshake PASSED:", [t["name"] for t in list_ok["result"]["tools"]])
        sys.exit(0)
    for line in sys.stdin:
        if line.strip():
            resp = handle_rpc(json.loads(line))
            if resp is not None:
                sys.stdout.write(json.dumps(resp) + "\n")
                sys.stdout.flush()Code language: Python (python)

Make the file executable and run --self-test in your terminal to confirm the MCP handshake works:

chmod +x regolo_harness_mcp.py
python3 regolo_harness_mcp.py --self-test
# Output: MCP stdio handshake PASSED: ['load_skill_on_demand', 'format_concise_tool_output']Code language: Bash (bash)

Step 2: Configure OpenCode (~/.config/opencode/opencode.json)

Export your Regolo API key (export REGOLO_API_KEY="your-key"), open ~/.config/opencode/opencode.json, and add both our European OpenAI-compatible provider (https://api.regolo.ai/v1) and the local regolo-context-harness server under the "mcp" section (replace /absolute/path/to/ with the folder where you saved the two Python files):

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "regolo": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Regolo (EU Zero Data Retention)",
      "options": {
        "baseURL": "https://api.regolo.ai/v1",
        "apiKey": "{env:REGOLO_API_KEY}"
      },
      "models": {
        "qwen3.8-27b": {
          "name": "Qwen3.8-27B",
          "limit": { "context": 240000, "output": 32000 }
        },
        "glm5.2": {
          "name": "GLM-5.2 (753B MoE)",
          "limit": { "context": 200000, "output": 32000 }
        },
        "gpt-oss-120b": {
          "name": "GPT-OSS 120B (237 tok/s)",
          "limit": { "context": 120000, "output": 16000 }
        }
      }
    }
  },
  "model": "regolo/qwen3.8-27b",
  "small_model": "regolo/gpt-oss-120b",
  "mcp": {
    "regolo-context-harness": {
      "type": "local",
      "command": ["python3", "/absolute/path/to/regolo_harness_mcp.py"],
      "environment": {
        "REGOLO_API_KEY": "{env:REGOLO_API_KEY}",
        "REGOLO_SKILLS_DIR": "/Users/yourname/.claude/skills"
      },
      "enabled": true
    }
  }
}Code language: JSON / JSON with Comments (json)

Step 3: Configure Claude Code (CLI command or project .mcp.json)

In Claude Code, run claude mcp add from the folder where you saved regolo_harness_mcp.py, then verify the server is connected with claude mcp list:

# Register the MCP stdio server in Claude Code
claude mcp add --transport stdio regolo-context-harness \
  --env REGOLO_API_KEY="$REGOLO_API_KEY" \
  --env REGOLO_SKILLS_DIR="$HOME/.claude/skills" \
  -- python3 "$(pwd)/regolo_harness_mcp.py"

# Confirm Claude Code sees the server as connected
claude mcp listCode language: Bash (bash)

If you want the configuration shared across your team via Git, create a .mcp.json file in your repository root instead:

{
  "mcpServers": {
    "regolo-context-harness": {
      "command": "python3",
      "args": ["/absolute/path/to/regolo_harness_mcp.py"],
      "env": {
        "REGOLO_API_KEY": "${REGOLO_API_KEY}",
        "REGOLO_SKILLS_DIR": "${HOME}/.claude/skills"
      }
    }
  }
}Code language: JSON / JSON with Comments (json)

Step 4: Configure OpenAI Codex CLI (~/.codex/config.toml)

In Codex CLI, open ~/.codex/config.toml and add both the Regolo European provider block and the [mcp_servers.regolo_context_harness] entry:

model = "qwen3.8-27b"
model_provider = "regolo"

[model_providers.regolo]
name = "Regolo EU Zero Data Retention"
base_url = "https://api.regolo.ai/v1"
env_key = "REGOLO_API_KEY"
wire_api = "chat"

[mcp_servers.regolo_context_harness]
command = "python3"
args = ["/absolute/path/to/regolo_harness_mcp.py"]
env = { "REGOLO_API_KEY" = "your-regolo-api-key", "REGOLO_SKILLS_DIR" = "/Users/yourname/.claude/skills" }Code language: TOML, also INI (ini)

Step 5: Generate the 1-line skill menu into AGENTS.md and CLAUDE.md

Finally, run this one-liner in your repository root to append the compact skill index and the on-demand calling rule into AGENTS.md (read by OpenCode and Codex CLI) and CLAUDE.md (read by Claude Code):

python3 -c '
from pathlib import Path
from piece1_progressive_skills import ProgressiveSkillRegistry
menu = ProgressiveSkillRegistry(Path("~/.claude/skills").expanduser()).compact_menu()
rule = """## Progressive skill disclosure & tool output rules
1. Do NOT preload full SKILL.md files into the conversation context.
2. When a task matches a skill below, call the MCP tool:
   load_skill_on_demand(skill_name="<name>", response_format="concise")
3. Pass verbose JSON payloads through format_concise_tool_output(raw_json=..., response_format="concise").

""" + menu + "\n"
for target in ["AGENTS.md", "CLAUDE.md"]:
    with open(target, "a", encoding="utf-8") as f:
        f.write("\n" + rule)
print("Appended compact skill menu to AGENTS.md and CLAUDE.md")
'Code language: Bash (bash)
PRACTICAL INTEGRATION · OPENCODE, CLAUDE CODE & CODEX

How to wire Piece 1 into your daily coding harness

Keep startup skill context at 293 prompt tokens while giving your agent on-demand access to every skill and concise tool output.

Agent · OpenCode
~/.config/opencode/opencode.json
Pair with qwen3.8-27b or glm5.2 on https://api.regolo.ai/v1
→
Local MCP Server
regolo-context-harness
load_skill_on_demand concise default
→
Outcome · Lean startup
35,685 → 293 tok (-99.18%)
Full skill docs enter context only when called (3,996 tok on Turn 2, -92.52%).
Agent · Claude Code
claude mcp add CLI
Works alongside local project CLAUDE.md files
→
One-line registration
claude mcp add regolo-harness
stdio transport -95.77% tool JSON
→
Outcome · Live GitHub REST API
17,794 → 753 tok (8 issues)
Strips avatar_url, node_id, and nested API URLs from GitHub issue dumps.
Agent · Codex CLI
~/.codex/config.toml
Point provider base_url at our EU endpoint
→
TOML MCP block
[mcp_servers.regolo_harness]
Qwen3.8-27B 0.79s Turn 1
→
Outcome · End-to-end Turn 1
53,452 → 1,019 tok (-98.09%)
Cuts Turn-1 latency from 7.63s to 0.79s on our EU API.

All four parts of our Context Engineering 101 kit share the same single-file regolo_harness_mcp.py server.

Explore the rest of the Context Engineering 101 series and related guides: Continue to Part 2 (Retrieve, offload, delegate) to keep 50k-token tool dumps out of your active window, Part 3 (Reversible compaction and prompt-cache-safe memory), and Part 4 (Long-running Initializer, Worker, and Evaluator harnesses). You can also explore our deep dives on context-mode and headroom, persistent codebase memory with ai-memory, our model comparison hub, and autonomous coding in VS Code with Roo Code, Qwen3.8-27B harness engineering for Pi, OpenCode, and Kilo Code, and IDE and agent integrations.

Frequently asked questions

What is the difference between prompt engineering and context engineering for AI agents?
Prompt engineering focuses on phrasing a single instruction, while context engineering manages the entire set of tokens entering and leaving the model window across dozens of turns, including system instructions, skill files, MCP tool schemas, and tool outputs.

Why do agents lose accuracy even when the model supports a 262K or 1M context window?
Every additional block of irrelevant instructions or raw UUIDs dilutes the attention budget of the transformer, a phenomenon known as context rot. Keeping the startup prefix lean preserves reasoning precision on later turns.

How does progressive disclosure work in OpenCode, Claude Code, and Codex?
Instead of loading full markdown guides for every skill at startup, the harness injects only a one-line name and summary per skill into the system prompt and exposes an on-demand tool so the model reads the full skill file only when a task requires it.

Why should I pass enable_thinking=False on routine harness turns with Qwen3.8-27B?
Reasoning models generate an internal scratchpad by default. Disabling thinking on deterministic formatting or routing calls avoids unnecessary latency and saves output tokens for steps that actually require deep planning.

Which models on the Regolo API work best with progressive skill disclosure?
GLM-5.2, Qwen3.8-27B, Qwen3.5-122B, and GPT-OSS 120B all support tool calling over our OpenAI-compatible EU endpoint, and all share the same flat €39/month Core token pool.

PRODUCTION-READY EU INFERENCE · ZERO DATA RETENTION OpenAI-Compatible API
Ship Private AI. Not Infrastructure.

You have the architecture and the open-source workflow. Now give it a sovereign European inference layer built for production: fast access to GLM-5.2, Qwen3.8-27B, GPT-OSS 120B, Gemma 4, Mistral, and Brick with zero data retention and no new SDK to learn.

DROP-IN ENDPOINT export OPENAI_BASE_URL="https://api.regolo.ai/v1" Keep your existing SDK & agent setup
Private AI should not require a private data center. We give your team an EU-native path from local experimentation to production-grade inference.