guide·intermediate·updated 2026-08-31

Build Self-Improving Agents: The Warp Pattern

Learn how Warp built self-improving agents using Claude Skills API. Step-by-step guide to agent feedback loops, inner/outer skill architecture, and production patterns.

AgentsClaude Platform

TL;DR: Most agents get 80% right then stop improving. Warp solved this using an inner skill + human feedback + outer improver skill pattern. Your agent learns from feedback, updates its own behavior, and compounds over time. Full implementation included.


The Problem Nobody Talks About

Your agent ships. It works. Then it keeps making the same mistakes.

Users submit tickets. "The agent missed this edge case." You manually fix the prompt. Deploy. Repeat next week.

This happens because agents have no memory. They execute, fail, and start fresh. Every session is a blank slate. Feedback vanishes when the session ends. There's no place for lessons to live.

This is the core problem with stateless agents: feedback disappears.

Real impact:

  • Code review agent makes bad comments → engineers complain
  • Issue triage agent misses labels → tickets get lost
  • Customer support agent repeats mistakes → escalations spike Warp hit this wall hard. So they invented a pattern that turns feedback into permanent agent improvement.

Why "Improving the Prompt" Doesn't Scale

Before building self-improving agents, most teams try:

1. Manual prompt tuning

  • You read feedback, rewrite the prompt
  • Works for 5 issues, breaks at 50
  • Doesn't scale across multiple agents
  • Knowledge dies when you leave 2. Context files (AGENTS.md)
  • Centralize instructions in a file the agent reads
  • Better than prompt rewriting, but:
  • Still manual updates
  • Hard to track what changed
  • Doesn't capture pattern across multiple runs
  • No way to know if changes actually helped 3. Fine-tuning the model
  • Expensive ($0.50-$2.00+ per 1M tokens)
  • Slow (wait days for retraining)
  • Can't update without redeploying
  • Permanent changes = risky Better solution: File-based skills that encode domain knowledge, updated automatically by an improver agent, with humans approving changes.

The Warp Solution: Inner/Outer Skill Pattern

Warp devised a simple two-skill architecture:

┌──────────────────────────────────────┐
│  INNER SKILL (Base Knowledge)        │
│  ─ Domain instructions               │
│  ─ How to do the job                 │
│  ─ Updated by humans + improver      │
└────────────────┬─────────────────────┘


        ┌─────────────────┐
        │  AGENT EXECUTES │
        │  (Every run)    │
        └────────┬────────┘


        ┌─────────────────┐
        │ HUMAN FEEDBACK  │
        │ (Issue comment) │
        └────────┬────────┘


┌──────────────────────────────────────┐
│  OUTER SKILL (Improver Agent)        │
│  ─ Runs on schedule (weekly)         │
│  ─ Reads all feedback                │
│  ─ Proposes edits to inner skill     │
│  ─ Changes go through PR workflow    │
└──────────────────────────────────────┘

How it works:

  1. Inner Skill: Your domain knowledge lives here. "For code review, look for unused variables. Check for N+1 queries. Suggest renames per our conventions."
  2. Agent Runs: Every time an issue is opened or PR is submitted, your agent reads the inner skill and executes using current knowledge.
  3. Human Feedback: When the agent misses something, a human leaves a comment explaining why. Example: "We don't rename this type of global variable—our convention is g_*. Update the rule."
  4. Improver Skill: On a schedule (daily/weekly), an observer agent wakes up. It:
    • Pulls all recent feedback
    • Compares what the agent suggested vs. how humans responded
    • Identifies patterns in failures
    • Proposes a small, focused edit to the inner skill
    • Opens a PR with the change
  5. Code Review: Because the change is a file, it goes through normal code review. A human approves it. Merged.
  6. Loop Closes: Next time your agent runs, it has the new knowledge built-in.

Implementation: Step by Step

Step 1: Create Your Inner Skill

Inner skills are plain text files. No code, no prompts—just principles.

Example: Code Review Inner Skill

# Code Review Agent Inner Skill
 
## Core Principles
Review code for:
- Performance issues: N+1 queries, unnecessary loops, unindexed searches
- Security gaps: Input validation, SQL injection, missing auth checks
- Maintainability: Unclear variable names, missing comments, over-engineered patterns
 
## Naming Conventions
- Global variables: Prefix with `g_`, e.g., `g_cache_timeout`
- Constants: UPPER_CASE, e.g., `MAX_RETRIES`
- Private functions: Prefix with `_`, e.g., `_validate_request()`
 
## When to Suggest Renaming
- Only suggest renames if they violate the naming conventions above
- Do NOT suggest stylistic renames ("x" → "element")
- Do NOT rename domain-specific abbreviations (e.g., "RPC" stays as-is)
 
## Red Flags (Always mention)
- Missing error handling in async operations
- Direct database queries without ORM
- Hardcoded timeouts or retry limits
 
## Confidence Threshold
Only suggest changes you're 80%+ confident about. If unsure, ask a clarifying question instead.
 
## Edge Cases
- If a function is under 50 lines, don't suggest refactoring
- If tests are missing entirely, mention but don't block the PR

This is human-readable. Your agent reads it at execution time.

Step 2: Wire Inner Skill into Your Agent

When your agent runs, load the inner skill and include it in context:

Pseudocode:

def run_code_review_agent(pr_details):
    # Load the inner skill
    inner_skill = load_file("skills/code_review_inner.md")
    
    # Include it in the system message
    system_prompt = f"""
    You are a code review agent. Follow these principles:
    
    {inner_skill}
    
    Review the PR below and provide constructive feedback.
    """
    
    # Call Claude with the skill
    response = claude.messages.create(
        model="claude-opus-4-8",
        system=system_prompt,
        messages=[
            {"role": "user", "content": f"Review this PR:\n\n{pr_details}"}
        ]
    )
    
    return response.content[0].text

Step 3: Capture Feedback (Make It Effortless)

Feedback only works if people actually give it. Low friction is key.

Feedback Capture Pattern:

Where people already work (PR comments, GitHub issues), make it automatic.

def process_github_feedback(issue_or_pr):
    # When someone leaves a comment on an issue the agent created,
    # extract feedback automatically
    
    comment_text = issue_or_pr["comment"]
    
    # Examples:
    # "Agent missed this label—should be 'ready to spec'"
    # "We don't rename global variables like this"
    # "This suggestion is wrong because X"
    
    # Store it with minimal friction
    feedback_entry = {
        "timestamp": now(),
        "context": issue_or_pr["url"],
        "feedback": comment_text,
        "human": issue_or_pr["author"],
        "agent_suggested": issue_or_pr["agent_output"]
    }
    
    store_feedback(feedback_entry)

Key: No extra submission step. No form. Just leave a comment, and it's captured.

Step 4: Build the Improver Skill

The improver skill is an observer agent that runs on schedule.

Improver Skill Logic:

def run_improver_agent():
    # 1. Fetch recent feedback
    recent_feedback = fetch_feedback(days=7)
    
    # 2. Summarize failures
    failure_summary = summarize_feedback(recent_feedback)
    # Example: "Agent suggested wrong label 3x. Should check 'ready to spec' 
    # when issue describes a real problem with undefined UX."
    
    # 3. Propose edit to inner skill
    improver_prompt = f"""
    You are the improver agent. Your job is to suggest a SMALL, FOCUSED edit
    to the inner skill based on human feedback.
    
    Feedback summary:
    {failure_summary}
    
    Current inner skill:
    {current_inner_skill}
    
    Propose ONE small edit (2-3 sentences max) that fixes the most common failure.
    Format: "OLD TEXT" → "NEW TEXT"
    """
    
    proposal = claude.messages.create(
        model="claude-opus-4-8",
        messages=[{"role": "user", "content": improver_prompt}]
    )
    
    # 4. Open PR with the change
    open_github_pr(
        title=f"Improve code review skill: {proposal.summary}",
        changes=proposal.diff,
        description=f"Based on {len(recent_feedback)} feedback items:\n\n{failure_summary}"
    )

Step 5: Route Through Normal Approval

Because the skill is a file, it flows through your normal code review:

PR opened by improver-bot
├─ Title: "Improve code review skill: Add check for 'ready to spec' label"
├─ Changes: +3 lines to skills/code_review_inner.md
├─ Description: Feedback showed we missed this label 3x this week

└─ Human reviews
   ├─ "Makes sense, approve"
   └─ Merged
   
Next agent run:
└─ Inner skill now has the new knowledge ✓

Real Example: Issue Triage Agent

Warp runs this across their entire open-source repo.

Inner Skill: skills/issue_triage_inner.md

  • What each label means (bug, feature, documentation, help-wanted)
  • When to assign label "ready-to-spec" (issue describes real problem, UX undefined)
  • When to assign label "good-first-issue" (isolated, well-defined, < 4 hours) Agent Runs: When GitHub issue is opened, agent analyzes it and suggests labels

Feedback Example:

Issue: "Warp startup is slow on M1 macs"
 
Agent suggested: bug, performance
 
Maintainer comment:
"Good catch on performance, but this needs investigation first. 
Don't label 'ready-to-spec' yet—we don't know if it's Warp or a user setup issue."

Improver Agent Runs: Weekly

Change Proposed:

OLD:
"ready-to-spec: Issue clearly describes the problem and proposed solution"
 
NEW:
"ready-to-spec: Issue clearly describes a real problem (reproducible, not user setup) 
even if the UI/solution shape isn't yet defined. Do NOT apply if investigation is needed."

Result: Next issue filed, agent applies the rule correctly.


Production Checklist

  • ✅ Inner skill written (principles, not rules)
  • ✅ Skill loaded into every agent execution
  • ✅ Feedback capture automatic (no extra steps)
  • ✅ Improver skill scheduled (daily/weekly)
  • ✅ Changes go through PR review (human approval)
  • ✅ Monitoring: track agent improvement over time
  • ✅ Safeguards: reject feedback that looks corrupted
  • ✅ Versioning: skills tracked in Git alongside code

Best Practices

Do:

  • Write principles, not rules ("Look for repeated code" vs. "Check for duplicates in lines 1-10")
  • Explain why ("We use g_* for globals because..." vs. just "Use g_*")
  • Capture feedback where people already work (issue comments, PR reviews)
  • Start small (one agent, one skill, one feedback loop)
  • Track metrics (feedback volume, improvements applied, failure rate trending) Don't:
  • Write exhaustive rules (agents generalize better from principles)
  • Make feedback submission hard (no forms, no extra clicks)
  • Approve all feedback blindly (humans review the proposed edits)
  • Run improver agent too frequently (daily/weekly is enough; hourly creates noise)
  • Expect perfect feedback (assume 10-20% is wrong; filter by domain experts)

Scaling to Multiple Agents

One agent = one inner skill.
Multiple agents = one improver skill template.

Code review agent
├─ Inner skill: code_review_inner.md
└─ Improver: improver-code-review (focused on this skill)
 
Issue triage agent
├─ Inner skill: triage_inner.md
└─ Improver: improver-triage (focused on this skill)
 
Spec writer agent
├─ Inner skill: spec_writer_inner.md
└─ Improver: improver-specs (focused on this skill)
 
All share:
└─ Feedback capture system (single channel for all agents)
└─ Approval workflow (standard PR review)

Cost & Time Breakdown

Component Cost Time
Inner skill (write initial) $0 2-3 hours
Agent integration $0 1-2 hours
Feedback capture $0 1 hour
Improver skill $0.10-0.30/week 2-3 hours setup
Human review (per change) $0 5-10 min
Total first month $0.50-$1.50 ~12-15 hours
Monthly ongoing $0.10-0.30 ~30 min/week

Compared to: Manual prompt rewriting (hours/week) or fine-tuning ($0.50-$2.00+ per training run).


Common Mistakes

Mistake Impact Fix
Inner skill is too detailed (100+ lines) Agent overwhelmed, ignores nuance Keep to 1-2 pages max
No feedback capture Loop never closes Automate where people already work
Improver runs too often Noisy, contradictory changes Daily/weekly, not per-run
No human approval Bad feedback corrupts skill Always review proposed changes
Skill in system prompt, not file Can't update without redeploying Use file-based skills
Metrics only on feedback volume Can't tell if improving Track agent success rate trending

Your Competitive Edge

Teams using self-improving agents:

  • Know which patterns work (data, not intuition)
  • Improve without retraining models (skip the cost + wait)
  • Scale to dozens of agents (one improver template handles many)
  • Keep humans in control (final approval on every change)
  • Ship features faster (automate the feedback loop)

Start this month. Write an inner skill. Integrate it into one agent. Capture feedback. Run your first improver pass. You'll never go back to static agents.


Next Steps

  1. Identify one agent that makes repeated mistakes
  2. Extract its logic into an inner skill (principles only)
  3. Integrate the skill into agent execution
  4. Run for 2 weeks collecting feedback (manually is fine)
  5. Build the improver and propose your first change
  6. Iterate. Track whether improvements stick. Questions? Check the Warp webinar for a live demo.

Got stuck, or want this shipped end-to-end for you? bitroot.club builds custom products for founders. →