<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/feeds/atom-style.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://wakeup-jin-blog.netlify.app/en/</id>
    <title>WakeUp-Jin</title>
    <updated>2026-07-31T04:42:45.963Z</updated>
    <generator>Astro-Theme-Retypeset with Feed for Node.js</generator>
    <author>
        <name>WakeUp-Jin</name>
        <uri>https://wakeup-jin-blog.netlify.app/</uri>
    </author>
    <link rel="alternate" href="https://wakeup-jin-blog.netlify.app/en/"/>
    <link rel="self" href="https://wakeup-jin-blog.netlify.app/en/atom.xml"/>
    <subtitle>WakeUp-Jin's personal blog on context engineering, Agent Harness and LLM application development.</subtitle>
    <rights>Copyright © 2026 WakeUp-Jin</rights>
    <entry>
        <title type="html"><![CDATA[Anthropic Hackathon Champion: Claude Code Configuration Guide]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/anthropic-hackathon-claudecode/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/anthropic-hackathon-claudecode/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Core patterns from the hackathon champion's Claude Code config collection — cross-session shared memory, continuous learning, checkpoint evaluation, code maps, and sub-agent orchestration.]]></summary>
        <content type="html"><![CDATA[<h2>Preface</h2>
<p>Analysis references:</p>
<ul>
<li>Hackathon champion Claude Code config collection: https://github.com/affaan-m/everything-claude-code</li>
<li>Anthropic official Skill configuration: https://github.com/anthropics/skills</li>
<li>ClaudeCode configuration docs: https://code.claude.com/docs/en/sub-agents</li>
</ul>
<h2>1. Cross-Session Shared Memory</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-64.hNeDppAV_Z1W7L4h.webp" alt="Cross-session shared memory" /></p>
<p>When using ClaudeCode, session records can be saved locally and resumed with the <code>resume</code> command. However, complete session records get compressed, and after multiple compressions, critical decision information gets diluted until completely forgotten. The four critical types of information are:</p>
<ol>
<li><strong>Which approaches worked (with verifiable evidence)</strong></li>
<li><strong>Which attempted approaches failed</strong></li>
<li><strong>Which approaches haven't been tried yet</strong></li>
<li><strong>Which work remains unfinished</strong></li>
</ol>
<p>To ensure these four types of information can be shared across sessions, we need a <strong>separate intermediate temporary session file</strong>.</p>
<p>This requires a complete <strong>automated file creation/saving workflow plus content-filling instructions</strong>, using three hooks:</p>
<ol>
<li><strong>PreCompact Hook</strong>: Before context compression, save important state to file</li>
<li><strong>SessionComplete Hook</strong>: At session end, persist learning outcomes or initialize file</li>
<li><strong>SessionStart Hook</strong>: At new session startup, auto-load prior context and output latest file path</li>
</ol>
<p>What content to fill and how?</p>
<ul>
<li>Content: Let Claude summarize session history based on the four information types above, or manually write key session information</li>
<li>Method: Mention it in chat, or create corresponding Skills and Commands</li>
</ul>
<p>Files used in this pattern:</p>
<ul>
<li>scripts/hooks/session-start.js</li>
<li>scripts/hooks/pre-compact.js</li>
<li>scripts/hooks/session-end.js</li>
</ul>
<h2>2. Continuous Learning and Memory Updates</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-65.CE5d9aQ0_Z1l5puz.webp" alt="Continuous learning workflow" /></p>
<p>Two trigger methods for continuous learning: <strong>Hook-mounted automatic scripts and Command manual execution</strong>.</p>
<p>Hook-based automatic approach uses three different-timed Hooks:</p>
<ol>
<li><strong>Stop Hook</strong>: Check session list length; if threshold met, output prompt info</li>
<li><strong>Sessionend Hook</strong>: Read complete session history; call claude via <code>claude -p "xxx"</code> to generate learning records</li>
<li><strong>PostToolUse Hook</strong>: Check session list length; inject "summarize learning record" instruction into tool return results</li>
</ol>
<p>Command-based manual approach: the <code>/learn</code> command</p>
<p>When users complete tasks and find design patterns worth saving to memory, trigger <code>/learn</code>.</p>
<p><strong>All summarized learning records are stored in /skill/learn folder, so the Agent can automatically use Skill learning records based on context.</strong></p>
<p>Files used: commands/learn.md, skills/continuous-learning</p>
<p>The difference between Session Files and Learning Files:</p>
<ul>
<li><strong>Learning Files (Learn Skill)</strong>: Global, permanent, abstract knowledge rules — <strong>purpose: avoid repeating mistakes, accumulate experience</strong></li>
<li><strong>Session Files (Session Tmp)</strong>: Local, temporary, specific work state — <strong>purpose: cross-session continuity</strong></li>
</ul>
<h2>3. Improving Project Maintainability — Evaluation + Dead Code Cleanup</h2>
<h3>3.1 Checkpoint-Based Evaluation</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-66.CQdfokTo_ZvQ2lj.webp" alt="Checkpoint-based evaluation" /></p>
<p>The flow is a three-step cycle: <strong>Start -&gt; Implement -&gt; Verify</strong>, constraining each feature.</p>
<ol>
<li><strong>Start</strong>: Before implementing, run the start command to ensure a clean workspace</li>
<li><strong>Implement</strong>: Write feature code — manually or with AI</li>
<li><strong>Verify</strong>: Run verification to evaluate code quality against requirements</li>
</ol>
<p>The start command (<code>/checkpoints create</code>):</p>
<ol>
<li>Execute <code>/verify quick</code> — only check build and type errors</li>
<li>Execute <code>git stash</code> or <code>commit</code> to save current state</li>
<li>Write SHA to <code>checkpoints.log</code> via <code>git rev-parse --short HEAD</code></li>
</ol>
<p>The verify command (<code>/checkpoint verify</code>):</p>
<ol>
<li>Get the latest SHA from checkpoints.log</li>
<li>Model calls <code>git diff</code> and runs relevant tests</li>
<li>Output a report with key metrics: new files, modified files, test pass rate, coverage, etc.</li>
</ol>
<p>This approach is elegant because <strong>the flow isn't forced automation — it only provides the minimum necessary condition: the SHA</strong>. How to get new/modified files, tests, and coverage metrics is determined by the model, maximizing model autonomy.</p>
<h3>3.2 Continuous Evaluation</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-67.BiGKSPHk_MELBQ.webp" alt="Continuous evaluation" /></p>
<p>Flow:</p>
<ol>
<li><strong>Trigger</strong>: Run every N minutes or after major changes</li>
<li><strong>Execute</strong>: Run full test suite, build status, code checks</li>
<li><strong>Results</strong>: Output detailed inspection report</li>
<li><strong>Decision</strong>: Determine if code passes; if not, proceed to fix</li>
<li><strong>Fix</strong>: Repair failing checks, then conclude</li>
</ol>
<p>Difference between the two evaluation approaches:</p>
<ol>
<li>Checkpoint-based: Suited for linear workflows with clear milestones</li>
<li>Continuous: Suited for long-running sessions</li>
</ol>
<p><strong>The deciding factor is task nature — checkpoint evaluation for feature implementation with clear stages, continuous evaluation for exploratory refactoring or maintenance without clear endpoints.</strong></p>
<h3>3.3 Dead Code Cleanup</h3>
<p>Uses a sub-Agent and a Command:</p>
<pre><code># Refactor Clean

Safely identify and remove dead code with test verification:

1. Run dead code analysis tools: knip, depcheck, ts-prune
2. Generate full report in .reports/dead-code-analysis.md
3. Categorize by severity: SAFE / CAUTION / DANGER
4. Only suggest safe deletions
5. Before each deletion: run tests -&gt; confirm pass -&gt; apply -&gt; test again -&gt; rollback if failed
6. Show cleanup summary

Never delete code before running tests!
</code></pre>
<h3>3.4 Code Maps — Trusted Context</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-68.Di2JgpHv_5zQIU.webp" alt="Code map" /></p>
<p>Code maps serve as an entry point for AI or developers to understand the codebase. AI can understand the project's global picture with fewer tokens through code maps. Keep documentation minimal and concise.</p>
<h3>3.5 Summary</h3>
<p>Four approaches to improving project maintainability:</p>
<ul>
<li><strong>Two verification methods (checkpoint and continuous) are sufficient to avoid most technical debt</strong> with appropriate intervention.</li>
<li><strong>Continuously updating code maps helps</strong>, as it records changelogs and how the code map evolves over time — providing a reliable information source beyond the repository itself.</li>
<li><strong>Through strict rules, Claude avoids creating messy .md files, duplicate files for similar code</strong>, and doesn't leave large amounts of dead code.</li>
</ul>
<h2>4. Sub-Agent Usage: Loop Verification + Orchestration</h2>
<p>Sub-agents exist to save context by returning summaries rather than full information. However, the orchestrator has semantic context that sub-agents lack.</p>
<blockquote>
<p>From @PerceptualPeak: "Your boss sends you to a meeting and asks for a summary. Nine times out of ten, he'll have follow-up questions. Your summary won't contain all the information he needs because you lack his implicit context."</p>
</blockquote>
<p>Two better approaches: <strong>loop verification calling pattern</strong> and <strong>sequential orchestrator</strong>.</p>
<h3>4.1 Loop Verification Calling</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-69.B7Ft8Y1j_1VUaKs.webp" alt="Loop verification calls" /></p>
<p>Flow:</p>
<ol>
<li>Main agent evaluates sub-agent results</li>
<li>If results are inadequate, main agent proposes new retrieval tasks</li>
<li>Sub-agent continues retrieval with new tasks</li>
<li>Maximum 3 rounds</li>
</ol>
<p><strong>In this pattern, tasks assigned to sub-agents should be "specific question + broader goal" to maximize retrieval coverage.</strong></p>
<h3>4.2 Orchestrator Agent</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-70.BIp1UEmN_flNj4.webp" alt="Agent orchestration" /></p>
<p>Principles:</p>
<ol>
<li>Each agent receives clear input and produces clear output</li>
<li>Output becomes input for the next stage</li>
<li>Never skip stages — each contains value</li>
<li>Use /clear between agents to keep context fresh</li>
<li>Store intermediate outputs in files (not just memory)</li>
</ol>
<p>Custom orchestration is also supported:</p>
<pre><code>/orchestrate custom "architect,tdd-guide,code-reviewer" "Redesign caching layer"
</code></pre>
<h2>5. Configuration File Reference</h2>
<p>By core functionality:</p>
<ol>
<li>Cross-session shared memory: session-start.js, pre-compact.js, session-end.js hooks</li>
<li>Continuous learning: commands/learn.md, skills/continuous-learning</li>
<li>Project maintainability: commands/checkpoint.md, commands/verify.md, skills/verification-loop, commands/refactor-clean.md, agents/refactor-cleaner.md, agents/doc-updater.md, commands/update-codemaps.md, commands/update-docs.md</li>
<li>Sub-agent usage: skills/iterative-retrieval, commands/orchestrate.md, agents/architect.md, agents/code-reviewer.md, agents/planner.md, agents/security-reviewer.md, agents/tdd-guide.md</li>
</ol>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-20T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Engineering Practices for Coding Agents: Lessons from OpenAI and Anthropic]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/agent-engineering-practice/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/agent-engineering-practice/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Core experiences distilled from OpenAI Codex and Anthropic Claude for building long-running, reliable Agent Harness systems.]]></summary>
        <content type="html"><![CDATA[<p>Related links:</p>
<ul>
<li>OpenAI's article: https://openai.com/zh-Hans-CN/index/harness-engineering/</li>
<li>Anthropic's article: https://www.anthropic.com/engineering/harness-design-long-running-apps</li>
</ul>
<h2>1. OpenAI's Practical Experience</h2>
<p>OpenAI's team attempted an experiment: <strong>build and ship an internal beta software product with no manually written code</strong>.</p>
<p>To accomplish this, the team needed to build a Harness for Codex that could run reliably over the long term. The software engineering team's primary work was no longer writing code, but <strong>designing environments, clarifying intent, and building feedback loops</strong>.</p>
<p>This enabled Codex to deliver a million-line project within weeks, already used by hundreds of internal users.</p>
<p>The core components of the coding Agent's Harness:</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/PzFubmMhJojjN7xZlL9cD7sJncc.UcUAztnG_ZRDvq0.webp" alt="OpenAI Codex Harness architecture" /></p>
<p><strong>Step 1: Three-Layer Code Review</strong></p>
<p>After Codex completes a task, it performs three layers of code review: self-review, local code review Agent, and cloud code review Agent. Only after all reviews pass can it proceed; otherwise, review results are injected back into Codex for revision.</p>
<p><strong>Step 2: Human QA</strong></p>
<p>As Codex's coding speed increased, the bottleneck became human QA. OpenAI integrated Chrome DevTools Protocol into Codex, enabling DOM snapshot processing, screenshots, and navigation — giving Codex direct UI analysis capability.</p>
<p><strong>Step 3: Log Detection and Performance Optimization</strong></p>
<p>The team also fed runtime logs and performance metrics into Codex, enabling practice -&gt; observe -&gt; modify cycles for performance optimization, rather than relying solely on code structure perception.</p>
<p><strong>Step 4: Code Documentation Library</strong></p>
<p>A codebase's detailed documentation is massive and can't be injected all at once. Using the "progressive disclosure" concept from the Skill specification, the documentation is delivered to Codex in a directory-file format.</p>
<p>OpenAI cleverly used AGENTS.md as the documentation index, containing file paths and brief descriptions. Whether to read and what to read is entirely up to Codex, making context utilization highly efficient.</p>
<p>A critical detail: feature requirements often go through team discussions. If this "discussion information" isn't documented for Codex, this context is missing from the Agent's runtime environment, potentially causing long-term directional drift.</p>
<p><strong>Step 5: Codebase Structural Rules</strong></p>
<p>Structural rules constrain the codebase to prevent chaos over time. For example, when Codex adds a feature, where to start and which structural layer to consider follows an ordering rule:</p>
<p><strong>Types -&gt; Config -&gt; Repository -&gt; Service -&gt; Runtime -&gt; UI</strong></p>
<p>Validation relies on custom code checkers (also written by Codex).</p>
<p><strong>Summary</strong>: The team applied <strong>mature software engineering practices</strong> to building Agent runtime environments:</p>
<blockquote>
<p>Software development still requires rigorous discipline, but that rigor is increasingly about scaffolding rather than the code itself.</p>
</blockquote>
<p>Key takeaways:</p>
<ol>
<li>Provide execution feedback for every step, creating feedback loops</li>
<li>Find specific constraints from general patterns for targeted scenarios</li>
<li>Provide more effective context — currently, "progressive document loading" is the best practice</li>
</ol>
<h2>2. Anthropic's Practical Experience</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/HQPXbkp3BoEsLrxM8wicr9Kzn2g.DYa9CVln_Z1tkRI9.webp" alt="Anthropic initial architecture" /></p>
<p>When building frameworks for long-running coding agents, Anthropic used a simple two-layer multi-agent architecture: <strong>task initialization Agent + coding Agent</strong>. As runtime increased and tasks grew complex, two common failure modes emerged:</p>
<ol>
<li>As the context window fills, the model loses coherence, with some models exhibiting "context anxiety" (especially Sonnet 4.5)</li>
<li>When designing self-evaluation modules, Agents asked to evaluate their own work tend to give confident, high praise</li>
</ol>
<p>For problem 1, the solution was <strong>context reset</strong>: completely clearing context (not just compression), starting a new Agent with structured handoff mechanisms.</p>
<p>For problem 2: <strong>separate the evaluation Agent from the execution Agent</strong>.</p>
<p>The team then built a three-Agent system:</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/NwPvbdrZzobMevxLaUycboiunXf.DRKihgEL_ZVNQn9.webp" alt="Anthropic three-Agent architecture" /></p>
<ol>
<li><strong>Planner</strong>: Takes 1-4 sentence prompts and expands them into full product specs</li>
<li><strong>Generator</strong>: Works in loops, executing one sub-task at a time</li>
<li><strong>Evaluator</strong>: Uses Playwright MCP to simulate user operations, testing UI, API endpoints, and database state, <strong>scoring against criteria</strong></li>
</ol>
<p>Two core practices:</p>
<ul>
<li><strong>Before each sub-task, the generator and evaluator negotiate a development contract</strong> — agreeing on completion criteria before writing any code</li>
<li><strong>Agents communicate via files</strong> — one Agent writes to a file, another reads it</li>
</ul>
<p>For evaluation criteria, Anthropic transformed subjective judgment into actionable rubrics: instead of "Is this design beautiful?", ask "Does it meet our design principles?" Their four criteria for frontend design: Design Quality, Originality, Craftsmanship, Functionality.</p>
<p><strong>Transform "vague subjective judgment" into "actionable scoring criteria".</strong></p>
<p>The final architecture after iteration:</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/LYyDbmNFko3eDaxQ19TcHHxfngf.IXcPg0SB_Z14nEBr.webp" alt="Anthropic final architecture" /></p>
<p>With Opus 4.6, they removed task splitting (Opus can handle full tasks) and development contracts (evaluator directly assesses final output).</p>
<p><strong>Summary: Harness design is not static — as model capabilities improve, the Harness needs additions and removals. An Agent's optimization isn't just changing model versions; some tools and modules may become obstacles that need removal.</strong></p>
<h2>3. Thinking About Harness from a Development Perspective</h2>
<ol>
<li>
<p>Build a review module — Agent output goes through review, with results injected back if review fails. Keep the review Agent separate from the execution Agent.</p>
</li>
<li>
<p>Use simple, effective message passing between Agents — markdown files work well: writing Agent writes to file, receiving Agent reads it.</p>
</li>
<li>
<p>Review modules need a "review specification" — criteria for what constitutes passing results. Transform subjective standards into objective ones: focus on "what are the standards for good results" rather than "is this result good?"</p>
</li>
<li>
<p>Follow the principle of simple and effective Harness construction. Understand it's dynamic and will continuously adjust with model upgrades. Use Agent evaluation to perceive changes rather than relying solely on intuition.</p>
</li>
<li>
<p>The current best multi-agent architecture pattern is: <strong>Plan - Execute - Evaluate</strong>.</p>
</li>
</ol>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-18T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Designing Browser Use for Your Agent]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/agent-browser-use/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/agent-browser-use/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[From CUA and DOM CUA to Playwright — core implementation approaches for Agent-controlled browsers, comparing Codex, Open-Browser-Use, and ActSpace architectures.]]></summary>
        <content type="html"><![CDATA[<p>There are many ways to let an Agent control a browser. You can embed a browser in your application (like Cursor and Codex), opening web pages within the app and using tool definitions for control. However, this approach can't inherit the user's full browser permissions or fully simulate user browser operations.</p>
<p>I prefer using browser extensions as intermediaries to control the user's original browser. Extensions can use Chrome API interfaces to read and operate tabs, and CDP-provided APIs to simulate human browser use — clicking, downloading, viewing, typing, etc.</p>
<p>Agent browser operation is complex with many nuances. This article serves as a primer for understanding the overall approach, while CDP, CUA, and Playwright details require more hands-on practice.</p>
<p>Research references:</p>
<ul>
<li>open-browser-use: https://github.com/iFurySt/open-browser-use</li>
<li>ActSpace: https://github.com/WakeUp-Jin/actspace-agent</li>
<li>Notch Agent: https://github.com/Puggo1145/Notch-Agent</li>
</ul>
<h2>1. Core Implementation Approaches</h2>
<p>Before implementing browser control, we need to understand the primitives for simulating human browser use:</p>
<blockquote>
<p>[!NOTE]
Primitives: viewing to confirm position, clicking, double-clicking, mouse movement, keyboard input, key presses, downloading, dragging, scrolling</p>
</blockquote>
<p>Chrome DevTools Protocol provides APIs for these primitive browser operations.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/browser-1.BRUn318B_1texL0.webp" alt="Core Browser Use implementation approach" /></p>
<p><strong>CUA (Computer Use Agent)</strong>: The most critical aspect is the source of all operations — "seeing." How does the Agent know which button to click and where it is?</p>
<p><strong>In CUA, the core is: screenshots to determine coordinates. With coordinates confirmed, corresponding operations can be executed. This requires multimodal model capabilities — image recognition.</strong></p>
<p>If the model lacks or has weak image recognition, we can use <strong>DOM CUA</strong> instead. Unlike CUA, <strong>DOM CUA doesn't use screenshot analysis to determine operation positions — it uses the DOM to locate elements and executes operations via node_id</strong>.</p>
<p>The key method in DOM CUA is <code>get_visible_dom</code>, which retrieves all visible DOM elements on the page as JSON, providing the Agent with node_ids for operations.</p>
<p><strong>Note: DOM CUA's method for getting all DOM elements internally calls CDP's native API, while other operations internally call pre-wrapped CUA functions.</strong></p>
<p>Beyond DOM CUA, we can use the mature browser automation framework <strong>Playwright</strong>, which offers many pre-built, complete, and safe execution flows. It can also use CSS selectors as operation conditions — much more granular than DOM CUA.</p>
<pre><code>-----Wait operation-------
CDP (DIY):
  Send Runtime.evaluate("document.querySelector('.result')")
  → If element hasn't loaded → returns null → fails
  → You must write while loops + sleep + retry + timeout handling

Playwright (auto-wait):
  wait_for(selector=".result", state="visible")
  → Internally auto-polls, checks state, handles timeouts
  → Only returns after element is truly visible
</code></pre>
<h2>2. Integrating with Your Agent</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/browser-2.BImbOYXA_Z1cMS6Y.webp" alt="Ways to integrate Browser Use with an Agent" /></p>
<p>Three approaches:</p>
<ol>
<li><strong>Embedded tools</strong>: Provide functions as a tool list for the Agent</li>
<li><strong>MCP server</strong>: Expose resource functions via MCP protocol</li>
<li><strong>Skill + CLI</strong>: Wrap functions as a CLI tool with a Skill as the "usage guide"</li>
</ol>
<h2>3. Complete Architecture Designs</h2>
<p>Three application architectures with different focuses and use cases:</p>
<p><strong>1. Codex's Browser Use</strong>: Most logic lives in Browser-client.js (~2,700 lines). The Rust extension-host serves as a simple message relay.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/browser-3.CHHlqYO8_FqYYs.webp" alt="Codex Browser Use architecture" /></p>
<p>Notable interaction details: mouse movement has starting positions with smooth transition clicking, and Agent-created tabs are visually distinguished from user tabs.</p>
<p><strong>2. Open-Browser-Use</strong>: Focuses on "open" — comprehensive caller support via Skill CLI, MCP connection, or direct SDK integration. Most business logic lives in the Go-based client.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/browser-4.Bhvoi5tU_vyG5g.webp" alt="Open-Browser-Use architecture" /></p>
<p><strong>3. ActSpace's Architecture</strong>: Drawing from both designs above, integrated directly into the project source code via a browser-tool file that defines what browser operations to provide to the Agent. The overall file is lightweight — just message forwarding and tool provision, without heavy business logic.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/browser-5.NyzZEy9Y_ZrsEpG.webp" alt="ActSpace Browser Use architecture" /></p>
<p>Core browser operation logic lives in the Go-based CLI, including browser extension connection processes. A useful detail: a <code>browser_help</code> command returns complete instruction descriptions and parameter details, greatly improving Agent accuracy when calling browser controls.</p>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-16T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Design Philosophy of the ActSpace Evaluation Module]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/actspace-eval-design/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/actspace-eval-design/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Relying on intuition and experience can get you started, but to go further, we need a rationale for optimization — the design practice of an Agent evaluation module.]]></summary>
        <content type="html"><![CDATA[<p>When building an Agent, we often start from intuition, or rather from experience.</p>
<p>We feel that adding this tool will be effective, that handling context this way will work, that structuring the prompt like this should be fine.</p>
<p>This approach, for an experienced LLM application engineer, will produce at least a passable Agent.</p>
<p>But what about the next step? If I want to make this Agent better, we fall into a state of confusion. We might look at other building approaches and experiences, but other people's experience built in different contexts may not apply to your current situation.</p>
<p>The main problem is: <strong>we don't know where the current Agent falls short — we can't quantify the details of Agent execution.</strong></p>
<p><strong>Relying on intuition and experience can get you started, but to go further, we need a rationale for optimization.</strong></p>
<p>We can turn our attention to Agent evaluation: build our own evaluation datasets from existing data, test with public datasets, observe issues in execution chains, and evaluate context quality based on actual execution environments.</p>
<p>Agent evaluation helps us determine the direction of Agent development, and provides powerful data so that each build decision can be more decisive.</p>
<p>Behind every great Agent, there must be a qualified Agent evaluation module.</p>
<p>I'm currently building ActSpace, a desktop Agent application. I've organized the design philosophy of its evaluation module here, hoping to provide some reference.</p>
<p>Research references:</p>
<ul>
<li>"Building an Agent Evaluation System": https://mp.weixin.qq.com/s/3VqbQzT9ruRVP9B4jlFAEg</li>
<li>"SWE-bench Lite": https://www.swebench.com/lite.html</li>
<li>"ActSpace Repository": https://github.com/WakeUp-Jin/actspace-agent</li>
</ul>
<h2>1. ActSpace's Agent Evaluation Module Design</h2>
<p>Let's start understanding this module from its inputs, which might be easier. The evaluation module I designed has three core input sources: <strong>behavioral evaluation datasets, internal datasets, and external public datasets</strong>.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/actspace-eval-design.CZ-bm4D4_2uBfok.webp" alt="ActSpace evaluation module design" /></p>
<p>For <strong>behavioral evaluation datasets</strong>, the main purpose is to evaluate the Agent's execution chain and context quality:</p>
<ul>
<li>Execution chain: whether necessary tools are called, whether the calling order is correct, how failures are handled, etc.</li>
<li>Context quality: whether tool results correctly enter the next round, whether task objectives are lost after compression, whether tool errors pollute the context, etc.</li>
</ul>
<p>For <strong>internal evaluation datasets</strong>, the main purpose is to distinguish from public datasets and prevent overfitting during optimization. This primarily evaluates the Agent's execution results. Worth discussing in detail is the <strong>method of building datasets: summarizing from failure cases and internalizing excellent datasets from peer Agents.</strong></p>
<p>The evaluation flow is: the Agent develops features or fixes bugs in a codebase based on user input, and after code completion, test files are executed. If all test cases pass, the Agent's task execution is considered successful.</p>
<p>So the core of the evaluator is: the codebase has complete test files and test execution commands.</p>
<p>For <strong>public evaluation datasets</strong>, we only run the Agent CLI and collect some information into prediction files, then the evaluator uses the official library's built-in Harness framework.</p>
<p>The core evaluation approach: in the same codebase, at the corresponding commit branch, <code>git apply</code> is used to apply the generated diff code to the codebase, then the corresponding test commands are executed. If all test cases pass, the Agent's modification is successful.</p>
<blockquote>
<p>[!NOTE]
This is similar to our internal dataset evaluation method, except the public evaluation dataset method is more complete, ensuring environmental consistency. The public evaluation dataset uses SWE-bench Lite.</p>
</blockquote>
<pre><code>// prediction.json file
{
  "instance_id": "django__django-11099",
  "model_name_or_path": "your-model-or-agent-name",
  "model_patch": "diff --git a/... b/...\n..."
}
</code></pre>
<p>The Agent CLI in the diagram is my packaging of ActSpace's core Agent module into a CLI command for easy invocation. Meanwhile, the test set execution environment is uniformly inside Docker containers, ensuring local environment safety.</p>
<p>After CLI execution completes, there's a post-run processor for data organization, which formats the Agent CLI output into various formats needed by the evaluation module.</p>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-15T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Making Agents Proactive: Scheduled Tasks and KAIROS Mode]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/agent-kairos-mode/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/agent-kairos-mode/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[From scheduled tasks to ClaudeCode's KAIROS mode — exploring designs that transform Agents from interactive to always-on background runners using Sleep tools and tick-driven events.]]></summary>
        <content type="html"><![CDATA[<h2>1. Scheduled Tasks</h2>
<p>Designing scheduled tasks lets Agents execute at specified times and send results — one way to make Agents "proactive," driven by timers. The core design: <strong>Agent produces, polling scheduler consumes</strong>.</p>
<p>Three core designs for adding scheduled tasks to an Agent:</p>
<ol>
<li><strong>Task storage</strong>: A JSON file stores scheduled tasks, read by the polling scheduler</li>
<li><strong>Polling scheduler</strong>: Reads the JSON file every second, executing tasks when conditions are met</li>
<li><strong>Three task tools</strong>: Create, query, and delete tools for the Agent</li>
</ol>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/W0jQbrcIsozdoCxQTAjcADeInpc.BfJz6I38_Z1wxrNm.webp" alt="Scheduled task design" /></p>
<p>Task storage uses JSON format with cron-formatted time expressions:</p>
<blockquote>
<p>[!NOTE]
Cron format easily expresses both one-time and recurring tasks with unified formatting for scheduling</p>
</blockquote>
<p>Two task creation methods: user input and <code>/loop</code> command.</p>
<ul>
<li><strong>User input</strong>: Model parses task time and instructions, calls the creation tool, writes to JSON</li>
<li><strong><code>/loop</code> command</strong>: More precise — constrains a complete time parsing rule, injects parsed input to the LLM, executes immediately on creation, and all tasks are recurring</li>
</ul>
<p><code>/loop</code> parsing rules:</p>
<ol>
<li>Leading interval: First space-separated number is the cron cycle time — <code>/loop 30m check deploy</code></li>
<li>Trailing "every": If input ends with "every N", N is the cycle time — <code>/loop run tests every 5 minutes</code></li>
<li>Default: If neither matches, default is 10 minutes</li>
</ol>
<pre><code>{
  "tasks": [
    {
      "id": "a1b2c3d4",
      "cron": "*/5 * * * *",
      "prompt": "Check deployment status",
      "createdAt": 1712830000000,
      "lastFiredAt": 1712830300000,
      "recurring": true
    }
  ]
}
</code></pre>
<p>For scheduler performance, consider caching: <strong>read cache every second, reload file every 5 seconds</strong>.</p>
<h2>2. KAIROS Mode</h2>
<p>ClaudeCode has a fascinating feature called <strong>KAIROS</strong> — transforming from interactive to always-on background mode, making the Agent proactive rather than passively reactive.</p>
<blockquote>
<p>Kairos comes from ancient Greek, a philosophical concept about time meaning "the right moment, the critical instant."</p>
</blockquote>
<p>All tasks the Agent handles are unified into a queue, allowing users to "single-thread" focus on tasks. The background-running assistant operates without interrupting the user's flow, proactively handling tasks at the right moments.</p>
<p>Queue tasks have priorities — not FIFO, but priority-based. User input has the highest priority.</p>
<p>KAIROS's continuous operation isn't controlled by simple while loops but by <strong>event-driven tick messages in context</strong> — very elegant.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/Nq5kb6T9Eoc56bxFuzqcoFjinjh.CTiy31f3_ZfMoTi.webp" alt="KAIROS mode design" /></p>
<ol>
<li>Each Agent run: pull task from queue by priority, determine if it's user input or KAIROS tick</li>
<li>User input: normal processing flow — Claude calls tools and reasons over context</li>
<li>Tick: switch to KAIROS-specific system prompt. Agent has two behaviors: execute tasks or sleep</li>
<li>Execute tasks: like normal mode — run tests, explore unfamiliar code, do small refactors</li>
<li><strong>Sleep</strong>: When the model determines there's nothing to do, it proactively enters "sleep state." Sleep duration is decided by the model itself, implemented via a sleep tool. User input can interrupt sleep at any time — it's a "first-class citizen" in the queue</li>
<li>After any task completes or sleep ends, one round is finished</li>
<li>Decision flow: if queue is empty, add a tick message; if not empty, proceed normally — this drives KAIROS's continuous operation</li>
</ol>
<p>Two design highlights I particularly appreciate:</p>
<p><strong>First: Sleep State Implementation</strong></p>
<p>Compared to scheduled tasks with fixed intervals (e.g., run every 30 minutes), that approach always felt somewhat forced — the "Agent proactivity" is really just user-configured scheduling.</p>
<p>In ClaudeCode's design, <strong>when to sleep and for how long is entirely up to the model.</strong> Users just "turn on" the Agent.</p>
<ul>
<li>System prompt adds judgment: "When you find no tasks to do, call the sleep tool"</li>
<li>Sleep tool has a <code>duration_ms</code> parameter controlled by the model</li>
</ul>
<p>This design feels much more genuinely "proactive."</p>
<pre><code>export const SleepTool = buildTool({
    name: 'Sleep',
    description: 'Wait for specified duration, user can interrupt anytime',
    inputSchema: z.strictObject({
      duration_ms: z.number().nonnegative().int().describe('Sleep duration (ms)')
    }),
    interruptBehavior: 'cancel',
    async call({ duration_ms }) {
      await new Promise(resolve =&gt; setTimeout(resolve, duration_ms))
      return { data: { slept_ms: duration_ms } }
    }
  })
</code></pre>
<p><strong>Second: Tick Messages</strong></p>
<p>Tick is the trigger source for KAIROS's <strong>event-driven loop</strong>. The mode runs continuously because after each task completion, a tick may be added to the queue — ensuring the queue always has a tick for the Agent to keep cycling.</p>
<p>A tick is essentially a message with a dynamic time variable:</p>
<pre><code>&lt;tick&gt;14:20:15&lt;/tick&gt;
</code></pre>
<p>Injected into model context as a user message:</p>
<pre><code>{"role":"user","content":"&lt;tick&gt;14:20:15&lt;/tick&gt;"}
</code></pre>
<p>KAIROS mode can serve as a paradigm for proactive Agent implementation. The core approach: <strong>Sleep tool + tick event-driven design</strong>.</p>
<p>This is more flexible than scheduled tasks, elegantly implemented, slightly more complex to develop (mainly queue state maintenance), but well worth trying if you want your Agent to run more proactively.</p>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-14T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Agent Bash Tool Engineering: Background Execution and Sandbox Design]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/agent-bash-engineering/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/agent-bash-engineering/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[From background mounting and incremental reading to macOS sandbox-exec three-layer sandbox — the two critical components for taking Agent Bash tools from demo to production.]]></summary>
        <content type="html"><![CDATA[<p>In the previous article, we covered the basic Bash tool design — good for demos or early project stages, but for production-grade Agent stability, two essential components are needed: <strong>background execution and sandbox design</strong>.</p>
<p>References:</p>
<ul>
<li>Previous article: "Bash Tool Implementation and Security Design"</li>
<li>Anthropic's lightweight sandbox tool: https://github.com/anthropic-experimental/sandbox-runtime</li>
</ul>
<h2>1. Context Management — Background Execution</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/agentbash1.CNKGD4XT_Zyi3CR.webp" alt="Bash Tool Background Execution and Incremental Reading" /></p>
<p>The Bash tool executes terminal commands. Some commands (like project startup) run for extended periods. Without a <code>blockMs</code> foreground time limit, the Bash tool execution would block. <strong>With blockMs, commands can be mounted to the background.</strong></p>
<p>Additionally, terminal read commands might read large files. Bash tool output is limited — when exceeding a threshold (currently 4000 characters), <strong>results are written to a temporary file, and the file path is returned</strong>. The model automatically reads via appropriate tools when needed.</p>
<p>Two key design points: <strong>background mounting and temporary file writing</strong></p>
<ol>
<li>
<p><strong>Temporary file writing</strong> prevents memory overflow and improves context efficiency — only necessary information enters context, read only when needed.</p>
</li>
<li>
<p><strong>Background mounting</strong> — the critical question is: how does the model access background command execution status? While the model could proactively read the file path, this is inefficient. So we designed <strong>incremental reading tool</strong> <code>bash_output</code> <strong>and event-driven push notifications</strong>.</p>
</li>
</ol>
<p>The incremental reading tool <code>bash_output</code> efficiently returns delta information (not full file content) plus background task status, giving the model better task awareness than a generic read tool.</p>
<p><strong>Event-driven push</strong>: Each time Bash output is written to the temporary file, a rule check triggers (regex or state-based). When conditions match, that output segment is pushed into the next turn's context.</p>
<blockquote>
<p>[!NOTE]
We don't use model-driven polling for task status — too inefficient. Instead, the task side proactively pushes when conditions are met.</p>
</blockquote>
<h2>2. Sandbox and Permission Design</h2>
<p>Sandbox and permission design have different focuses:</p>
<ul>
<li><strong>Permission design</strong>: Should this command need user review? Can it execute?</li>
<li><strong>Sandbox design</strong>: After execution, how much damage can it do? Ensuring execution safety as a last line of defense.</li>
</ul>
<p>On macOS, use the built-in sandbox mechanism with a Profile syntax file:</p>
<blockquote>
<p>[!TIP]
Simply prefix command execution with <code>/usr/bin/sandbox-exec -f profile.sb</code> to start the process. Constraints are enforced by the kernel and automatically inherited across the entire process tree.</p>
</blockquote>
<p>The complete three-layer design: first intercept known dangerous commands, then execute in sandbox. If sandbox execution fails due to permission restrictions, enter real environment execution — but always ask the user first.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/agentbash2.Dw9yIVjo_ZeYXwi.webp" alt="Three-layer Sandbox and Permission Design" /></p>
<p>When the sandbox fails due to permissions, <strong>transform the failure signal</strong> — otherwise the Agent sees EPERM errors and assumes the command itself is wrong, not that sandbox permissions are insufficient. Add a hint: "This may be blocked by the sandbox, not a command error."</p>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-12T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Demystifying AI Agent Evaluation: Methods for Different Agent Types]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/agent-eval-methods/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/agent-eval-methods/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[From coding Agents to conversational Agents, research Agents to computer-use Agents — evaluation methods, perspectives, and pass@k / pass^k metrics.]]></summary>
        <content type="html"><![CDATA[<h2>Preface</h2>
<blockquote>
<p>[!NOTE]
The previous article "Agent Evaluation" covered macro-level evaluation concepts. This article dives into specific evaluation methods and perspectives for different types of Agents.</p>
</blockquote>
<p>Analysis references:</p>
<ul>
<li>Article: https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents</li>
<li>𝜏-Bench: https://arxiv.org/abs/2406.12045</li>
<li>τ2-Bench: https://arxiv.org/abs/2506.07982</li>
<li>BrowseComp: https://arxiv.org/abs/2504.12516</li>
</ul>
<h2>1. Evaluating Coding Agents</h2>
<p>Coding Agents' main tasks: writing, testing, and debugging code, browsing codebases like human developers. They rely on clearly specified tasks, which means <strong>deterministic scorers are ideal for coding Agents</strong>.</p>
<p><strong>First evaluation focus: Does the code run? Do tests pass?</strong></p>
<p>Two programming benchmarks:</p>
<ol>
<li>SWE-bench Verified</li>
<li>Terminal-Bench</li>
</ol>
<blockquote>
<p>[!NOTE]
Terminal-Bench tests complete compilation processes (end-to-end), not just fixing single compile errors — e.g., deploying web apps, setting up MySQL from scratch.
SWE-bench Verified is more like "unit testing": give the Agent a real problem, it writes fix code, then run the test suite.</p>
</blockquote>
<p><strong>Second evaluation focus: Is the Agent's work process reasonable and efficient?</strong></p>
<p>Beyond just testing results, evaluating the process of task completion is valuable. Two additional evaluation methods:</p>
<ol>
<li><strong>Heuristic-based code quality evaluation</strong>: Check code quality with rules rather than just test results — complexity, duplication, naming conventions, security vulnerabilities, performance issues, readability</li>
<li><strong>Model-based behavioral evaluation</strong>: Use an LLM to evaluate the Agent's intermediate process</li>
</ol>
<p>Example: Task A — Query user info from database</p>
<ul>
<li>Agent A: Queries all users, filters in memory</li>
<li>Agent B: Uses WHERE clause for conditional query</li>
</ul>
<p>Both complete the task, but Agent B is better and more standards-compliant.</p>
<p><strong>Conclusion: Coding Agent evaluation should assess both execution results and execution process.</strong></p>
<p>Complete evaluation case:</p>
<pre><code>task:
  id: "fix-auth-bypass_1"
  desc: "Fix authentication bypass when password field is empty..."
  graders:
    - type: deterministic_tests
      required:
        - test_empty_pw_rejected.js
        - test_null_pw_rejected.js
    - type: llm_rubric
      rubric: prompts/code_quality.md
    - type: static_analysis
      commands:
        - eslint
        - tsc
    - type: state_check
      expect:
        security_logs:
          event_type: "auth_blocked"
    - type: tool_calls
      required:
        - tool: read_file
          params:
            path: "src/auth/*"
        - tool: edit_file
        - tool: run_tests
  tracked_metrics:
    - type: transcript
      metrics:
        - n_turns
        - n_toolcalls
        - n_total_tokens
    - type: latency
      metrics:
        - time_to_first_token
        - output_tokens_per_sec
        - time_to_last_token
</code></pre>
<h2>2. Evaluating Conversational Agents</h2>
<p>Conversational agents interact with users in domains like support, sales, or coaching. Unlike traditional chatbots, they maintain state, use tools, and take actions mid-conversation.</p>
<blockquote>
<p>[!IMPORTANT]
While coding and research agents may also involve multiple user interactions, <strong>conversational agents present a unique challenge: the quality of interaction itself is part of what you evaluate</strong>.</p>
</blockquote>
<p>Effective evaluation relies on <strong>verifiable final-state outcomes and rubrics capturing both task completion and interaction quality</strong>, often requiring a second LLM to simulate users.</p>
<p><strong>First focus: Verifiable final state</strong> — the task the conversational Agent must ultimately complete (refund processing, address changes, quote generation, etc.)</p>
<p><strong>Second focus: Interaction quality is also part of evaluation</strong></p>
<p>Example — Customer refund scenario:</p>
<p>Agent A: "Order number?" → "Refunded." (Task complete but curt)</p>
<p>Agent B: "I'm sorry for the inconvenience. Which order?" → "I've found your order — it qualifies for a refund. Processing now, expect 3-5 business days. Anything else I can help with?" (Task complete, great experience)</p>
<p><strong>Conclusion: Conversational Agent evaluation = final state verification + interaction quality assessment</strong></p>
<p>Multi-dimensional effectiveness criteria:</p>
<ol>
<li>Was the user's issue resolved? (state check)</li>
<li>Completed within 10 conversation turns? (context constraint)</li>
<li>Was the tone appropriate? (LLM evaluation)</li>
</ol>
<p>Notable benchmarks: <strong>𝜏-Bench and τ2-Bench</strong>, simulating multi-turn interactions in retail support and airline booking.</p>
<h2>3. Evaluating Research Agents</h2>
<p>Research Agents collect, synthesize, and analyze information to produce outputs like answers or reports.</p>
<p>Evaluation can't be as deterministic as coding Agent unit tests. <strong>Output quality can only be judged relative to the task, primarily on:</strong></p>
<ul>
<li>Comprehensive search and research</li>
<li>Good and correct sources</li>
</ul>
<p>Different domains require different standards (market research vs technical investigation).</p>
<p><strong>Research Agent evaluation faces unique challenges: experts may disagree on synthesis completeness, ground truth changes with references, and longer open-ended outputs create more room for errors.</strong></p>
<p>Notable benchmark: <strong>BrowseComp</strong> — tests whether AI agents can find needles in the open web. Questions are designed to be easy to verify but hard to solve.</p>
<p>General evaluation approach — combine multiple scorer types:</p>
<ol>
<li><strong>Grounding check</strong>: Does every claim have source support?</li>
<li><strong>Coverage check</strong>: Are key insights from sources included and used?</li>
<li><strong>Source quality check</strong>: Are citations authoritative?</li>
</ol>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-56.DXEyH7-5_1zqj1Q.webp" alt="Evaluating research Agents" /></p>
<h2>4. Evaluating Computer-Use Agents</h2>
<p>Computer-use Agents interact with software through the same interfaces as humans: screenshots, mouse clicks, keyboard input, and scrolling — not through APIs or code execution. <strong>They can use any program with a GUI.</strong></p>
<p>Evaluation must check not just UI appearance but whether backend logic executed correctly:</p>
<ol>
<li><strong>WebArena</strong>: Tests browser-based tasks using URL and page state checks, plus backend state verification for data-modifying tasks</li>
<li><strong>OSWorld</strong>: Extends to full OS control — evaluation scripts check file system state, app configs, database content, and UI element properties</li>
</ol>
<p>A critical design consideration from the official source:</p>
<blockquote>
<p>[!TIP]
Browser-use agents must balance token efficiency and latency. DOM-based interaction is fast but token-heavy; screenshot-based interaction is slower but more token-efficient.</p>
</blockquote>
<p>Guidance for browser Agent development:</p>
<ol>
<li>If the webpage is text-heavy, reading DOM elements directly is more efficient</li>
<li>If the webpage has many DOM elements with scattered text (e.g., e-commerce), screenshots may be more efficient</li>
</ol>
<h2>5. Summary</h2>
<p>Regardless of agent type, agent behavior varies between runs, making evaluation results harder to interpret than they initially appear.</p>
<p>Two metrics capture this nuance:</p>
<p><strong>1. pass@k measures the probability of getting at least one correct solution in k attempts.</strong></p>
<p>As k increases, pass@k rises — more "shots on goal" means higher chance of at least 1 success.</p>
<p>50% pass@1 means the model succeeded on half the tasks on its first attempt. In programming, we usually care most about pass@1.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-55.Cqq3GajB_ZyyRrW.webp" alt="pass@k example" /></p>
<p>Example: 5 tasks, 3 succeeded at least once within 3 attempts → pass@3 = 60%</p>
<p><strong>2. pass^k measures the probability of all k trials succeeding.</strong></p>
<p>As k increases, pass^k drops — maintaining consistency across more trials is harder.</p>
<p>If your agent has 75% per-trial success rate over 3 trials, all-3-passing probability is (0.75)³ ≈ 42%. Critical for user-facing agents where reliable behavior is expected every time.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-58.CtAUrezw_Z20sA1n.webp" alt="Divergence between pass@k and pass^k" /></p>
<ul>
<li><strong>pass@k represents capability</strong> — what the Agent can do given enough chances, its boundary</li>
<li><strong>pass^k represents stability</strong> — how reliable the Agent is</li>
</ul>
<blockquote>
<p>[!NOTE]
At k=1, they're identical. By k=10, they diverge completely: pass@k approaches 100% while pass^k drops to 0%.</p>
</blockquote>
<p><strong>Both are useful — which to use depends on product needs: for tools, one success matters (pass@k); for agents, consistency is key (pass^k).</strong></p>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-12T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Tool Dispatch and Permission Module Development]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/tool-dispatch-permission/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/tool-dispatch-permission/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Designing Agent tool execution dispatch — 7 state machine states, 4 permission modes, configuration file rule systems, and allowList mechanisms. Referencing ClaudeCode, Gemini-cli, OpenCode, and Kode.]]></summary>
        <content type="html"><![CDATA[<p>The core of tool permission mode development is designing Agent modes to determine whether tools need user approval before execution. This extends into <strong>tool dispatch implementation and allowList mechanisms</strong>.</p>
<p>Complete development approach:</p>
<ol>
<li>Tool permission verification methods and terminal approval panels</li>
<li>Tool execution dispatch</li>
<li>AllowList mechanism</li>
</ol>
<p>References: Gemini-cli, OpenCode, Kode, ClaudeCode</p>
<h2>1. Tool Dispatch Flow Design</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/XiqibKuhCo6vHfxflwQcGdq9n73.Bo3_SPQ-_1TKeRN.webp" alt="Tool Dispatch Flow" /></p>
<p>Tool execution states:</p>
<ol>
<li><strong>validating</strong>: Verifying parameters and pre-conditions</li>
<li><strong>awaiting_approval</strong>: Waiting for user approval</li>
<li><strong>scheduled</strong>: Ready to execute, awaiting batch execution</li>
<li><strong>executing</strong>: Currently running</li>
<li><strong>success</strong>: Completed successfully</li>
<li><strong>error</strong>: Execution failed</li>
<li><strong>cancelled</strong>: User cancelled or process interrupted</li>
</ol>
<h2>2. Permission Verification Method Design</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/Qz9jbUbvXo941oxk3RNcCPLknve.GPiQZRz2_cwO1u.webp" alt="Four Permission Modes" /></p>
<p>Four permission modes:</p>
<ol>
<li><strong>Plan mode</strong>: Edit and command execution tools completely disabled</li>
<li><strong>Default mode</strong>: All tools available but require approval</li>
<li><strong>Edit mode</strong>: All tools available; edit tools auto-approved, command tools still require approval</li>
<li><strong>Auto mode</strong>: All tools available and auto-approved</li>
</ol>
<p>Each tool has a <strong>verification function</strong> whose core logic:</p>
<ol>
<li>Get the current mode from frontend</li>
<li>Determine if the tool needs approval based on mode</li>
<li>For command execution tools, additionally check the allowList</li>
</ol>
<p>When verification requires approval, the user gets three choices:</p>
<ul>
<li><strong>Execute once</strong>: Approve this single execution</li>
<li><strong>Allow for this session</strong>: Auto-approve all subsequent uses of this tool in the session</li>
<li><strong>Cancel</strong>: Deny execution</li>
</ul>
<p>"Allow for session" behaves differently for two tool categories:</p>
<ol>
<li><strong>Command tools</strong>: Use allowList to store command "prefixes" for future prefix validation</li>
<li><strong>Edit tools</strong>: Switch mode to "Edit mode"</li>
</ol>
<h2>3. Permission Configuration File Design</h2>
<p>The built-in verification function approach makes developers active and users passive — users can't customize individual tool verification behavior.</p>
<p>To improve this, <strong>flip the perspective: make tools passive and users active</strong> — users control tool verification via configuration files:</p>
<pre><code>{
  "permissions": {
    "allow": ["Read", "Bash(git *)"],
    "deny": ["Bash(rm -rf*)"],
    "ask": ["Bash(npm publish*)"]
  }
}
</code></pre>
<p>ClaudeCode has 8 configuration sources (userSettings, projectSettings, localSettings, flagSettings, policySettings, cliArg, command, session) — permission rules from all sources are additive, not overriding.</p>
<p>Complete permission verification system:</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/IZFgblnV0otIZgx7TJEc2f6cnSe.CjOsii0q_1XVtRN.webp" alt="Complete Permission Verification System" /></p>
<ol>
<li>Two-layer verification with priority: <strong>rule check first, tool verification function second</strong>. If rules pass, execute directly without further verification.</li>
<li><strong>deny (reject)</strong>: Called twice — first at tool registration (matching tools aren't registered, invisible to the model), second during execution-phase permission verification (necessary for dynamic tool loading or rule changes).</li>
<li><strong>allow (permit)</strong>: Executed <strong>after</strong> the tool's own verification function. When users configure allow rules, and the tool's self-verification outputs "ask" or "passthrough," allow silently overrides those states.</li>
</ol>
<h2>4. Terminal Display</h2>
<p>Tool execution states drive CLI terminal displays using publish-subscribe event notifications:</p>
<ul>
<li>validating → show "waiting" status</li>
<li>awaiting_approval → show approval panel for user selection</li>
<li>executing → show execution in progress</li>
<li>success/error/cancelled → display as tool execution results</li>
</ul>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/Gk1ObQjtHoG1zAxzUD0czw0Onkc.BUqWVMF9_Z13w46f.webp" alt="Terminal Approval Panel" /></p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/Juw2bmArkogn6txHuPIcbI0dnye.Bx0vpCqq_Z1OVLfr.webp" alt="Tool Execution Status Display" /></p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/DILyb8o5wo1Df2xkGckcTAUpnqb.Ca6vvSjU_1k3KP7.webp" alt="Tool Execution Result Display" /></p>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-11T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Multi-Agent Collaboration: Agent Team and Agent Room]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/agent-team-room/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/agent-team-room/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Exploring two core multi-agent collaboration patterns — Agent Team (temporary team tackling) and Agent Room (equal discussion), plus task scheduling and member design.]]></summary>
        <content type="html"><![CDATA[<p>I've been practicing multi-agent design patterns recently and considering adding multi-agent capabilities to ActSpace. Well-designed multi-agent systems can improve results while reducing costs — cost control brings excellent user experience for application teams, which I consider part of Harness Engineering.</p>
<p>Through continuous exploration, I've found multi-agent design, especially collaboration aspects, to be fascinating and challenging. This appears to be a major breakthrough direction for mature Agents — as we can see from ClaudeCode's Agent Team and Dynamic Workflows.</p>
<p>Below are some of my explorations and thoughts on multi-agent collaboration.</p>
<p>Research references:</p>
<ul>
<li>"Is Having Agents in the Room Meant to Be Chaotic?": https://raft.build/resources/blog/is-having-agents-in-the-room-meant-to-be-chaotic/</li>
<li>"multica open source project": https://github.com/multica-ai/multica</li>
<li>"Model and effort in Claude Code": https://x.com/ClaudeDevs/status/2074900291062034618</li>
</ul>
<h2>1. Agent Team Design</h2>
<p>Agent Team is a multi-agent collaboration pattern similar to a "temporary team" tackling a complex task together. It includes a Lead role and Teammates, with communication happening not just between Lead and members, but also between members.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/AR-AT-1.D3PTLp7__Z2n1CpG.webp" alt="Agent Team architecture" /></p>
<p><strong>Four core components of an Agent Team: Team Lead, Task List, Team Members, and Message Inbox</strong></p>
<p>Core execution steps:</p>
<ol>
<li>Team Lead generates a task list based on task complexity and creates basic team information</li>
<li>Lead can directly assign tasks to members; idle members can also proactively claim tasks</li>
<li>Communication between Lead and Teammates goes through an inbox (message inbox), similar to sending emails in human collaboration</li>
</ol>
<p>Team Lead creates tasks and team info using two tools: taskCreate and TeamCreate, which create two key folders:</p>
<pre><code>~/.claude/teams/jink-team/
~/.claude/tasks/jink-team/
</code></pre>
<p><strong>How are tasks distributed?</strong></p>
<p>Agent Team uses <strong>Lead assignment and member self-claiming</strong>. Lead uses TaskUpdate; members use TaskList to check status, then claim based on status. This is implemented by a loop scheduler executing every 500ms.</p>
<p>The most critical part — team collaboration: communication signals in Agent Team are of two types: <strong>information and instructions</strong>, passed through the message inbox.</p>
<ol>
<li>Information: content, task descriptions and inputs — same as normal user input</li>
<li>Instructions: hard signals like permission approval notifications, process shutdown, etc.</li>
</ol>
<p>The inbox is a simple JSON file with read/unread status. Each Agent's execution loop repeatedly reads this file; new messages are injected into context for the next round.</p>
<p>Agent Team's message passing uses simple <strong>files + scheduler</strong> — very effective. The most critical implementation detail is <strong>file lock design</strong>.</p>
<p>For example, two Agents might simultaneously read the same task, creating unstable state. File locks ensure only one Agent reads and modifies at a time.</p>
<p>ClaudeCode's team implemented this elegantly using <code>mkdir</code> — which is atomic on the filesystem: only one process can successfully create the same directory.</p>
<pre><code>tasks/jink-team/
  3.json          ← actual task content
  3.json.lock/    ← "someone is modifying 3.json" (physical form of the lock)
</code></pre>
<h2>2. Agent Room Design</h2>
<p>Agent Room is another multi-agent collaboration pattern — no "Lead", just equal exchange: mutual discussion, sharing opinions, intellectual collision in a shared room.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/AR-AT-2.DprrLgjX_ZzN33U.webp" alt="Agent Room architecture" /></p>
<p>The core of Agent Room lies in active vs passive context. If you start from a chat room and pull Agents in, every message floods into each Agent's context passively — terrible from a context management perspective.</p>
<p>Every message injected into context gets the model's attention. Too much irrelevant or conflicting information interferes with Agent decision-making.</p>
<p>A better approach uses two concepts: <strong>Inbox and Draft Board</strong></p>
<ul>
<li><strong>Inbox</strong>: Chat room messages go into the Agent's inbox, but what gets pushed into Agent context is entirely the Agent's decision — it selectively pulls messages</li>
<li><strong>Draft Board</strong>: Before each output to the chat room, the Agent checks if the inbox has been updated. If not, output directly. If updated, the message is held and re-injected with additional info for re-evaluation. The Agent then has four choices: modify, send as-is, discard, or force send.</li>
</ul>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/AR-AT-3.V-M85TBU_Qe97s.webp" alt="Agent Room inbox and draft board" /></p>
<p>I have another approach to consider — no inbox or draft board, but chat messages are pushed directly into Agent context, with an added concept: <strong>Thought Sprites (sub-Agents)</strong>.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/AR-AT-4.TzVBtXsw_1zqf2G.webp" alt="Thought Sprite-based Agent Room" /></p>
<p>The idea: the Agent doesn't execute tasks but distributes them to Thought Sprites, then waits for sub-agent results for comprehensive analysis. Before replying, it calls a tool to "seize the speaking token" — like raising your hand to speak in class. Upon success, the Agent gets exclusive chat room access for its response.</p>
<p><strong>This is just a hypothesis — I haven't practiced it yet. Interested readers are welcome to try!</strong></p>
<h2>3. Agent Task Design</h2>
<p>A Task is the smallest execution unit for an Agent. One Task can only be executed by one Agent, but one Agent can execute multiple Tasks simultaneously.</p>
<p>Task generation patterns from the two designs above:</p>
<ol>
<li><strong>Agent Team tasks</strong>: Complex tasks split into smaller ones — temporary tasks</li>
<li><strong>Agent Room tasks</strong>: User-specified tasks for specific members — complete tasks</li>
<li><strong>Timed tasks</strong>: Tasks with time attributes that execute on schedule</li>
</ol>
<p>Multi-agent projects can have a Task module displaying current tasks by status or by Agent.</p>
<h2>4. Agent Member Design</h2>
<p>In multi-agent coordination, the Member role is crucial. Members need complete definitions: identity, avatar, name, settings, tools, scope, memory, etc.</p>
<p>Such Members work directly in Agent Room as room members — one Member can join multiple rooms with isolated sessions.</p>
<p>In Agent Team, if Members are always the same fixed group, it defeats the purpose of temporary teams. A design consideration: Members can have "avatars" — team members in Agent Team are essentially Member avatars with some core attributes unchanged but others variable. Same Member, different "avatars" across Teams.</p>
<blockquote>
<p>In Agent Team, Member positioning design isn't the most important thing — what matters is assembling the right team for each complex task.</p>
</blockquote>
<p>This unifies Member design across Team and Room for consistent maintenance.</p>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-10T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Bash Tool Implementation and Security Permission Design]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/bash-tool-impl/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/bash-tool-impl/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Complete Agent Bash tool implementation — tool definition, Generator execution pattern, return value design, 24 static security check rules, and three-layer permission verification.]]></summary>
        <content type="html"><![CDATA[<h2>1. Bash Tool Implementation</h2>
<p>The Bash tool is a critical foundational Agent tool — Skill scripts need it, and as applications become increasingly CLI-based, future Agent external application calls will need it too.</p>
<p>While the Bash tool enables many operations and can simplify the Agent's tool list, <strong>maintain the principle of least privilege</strong> — use dedicated tools first (Read for reading, Edit for editing, etc.).</p>
<h3>1.1 Tool Definition</h3>
<p>Key parameters:</p>
<ul>
<li><strong>command</strong>: Bash command string to execute</li>
<li><strong>timeout</strong>: Execution timeout to prevent Agent hangs</li>
<li><strong>description</strong>: Brief description rendered to users in UI</li>
<li><strong>run_in_background</strong>: For long-running commands (builds, server starts) — run in background, poll for results</li>
<li><strong>dangerouslyDisableSandbox</strong>: Security bypass strategy</li>
<li><strong>_simulatedSedEdit</strong>: Pre-computed sed results — on user approval, writes the result directly instead of re-executing sed, ensuring WYSIWYG</li>
</ul>
<h3>1.2 Execution Function</h3>
<p>Three core design principles:</p>
<ol>
<li><strong>Generator function</strong> for real-time output streaming</li>
<li>Production-grade <strong>exec wrapper</strong></li>
<li><strong>Content length checking</strong> — large outputs written to file, returning partial results + file path</li>
</ol>
<p>Generator mode is superior to Promise mode: Generator yields intermediate states in real-time, while Promise requires waiting until completion with a blank period.</p>
<p>The exec wrapper provides:</p>
<ol>
<li><strong>Output written to disk</strong> — only ~4KB preview in memory</li>
<li><strong>Active interruption</strong> via AbortSignal</li>
<li><strong>Timeout handling</strong> — auto-stop after 120s</li>
<li><strong>Merged stdout/stderr</strong> for consistent UI display timing</li>
<li><strong>CWD auto-recovery</strong> when the working directory is accidentally deleted</li>
</ol>
<p>Output truncation: files under 128KB are returned inline; larger outputs get the first 128KB preview plus the full file path for on-demand reading.</p>
<h3>1.3 Return Values</h3>
<p>Key fields:</p>
<ul>
<li><strong>returnCodeInterpretation</strong>: Semantic explanation of non-zero exit codes for better model reasoning</li>
<li><strong>persistedOutputPath</strong>: Large output file path — the model decides whether to read the full output based on context, rather than blindly injecting everything</li>
<li><strong>stdout</strong>: Core command output</li>
</ul>
<h3>1.4 Permission Verification Flow</h3>
<p>The Bash tool has the broadest execution scope and highest risk. Verification includes:</p>
<ol>
<li>Command parsing</li>
<li>Static rule checking</li>
<li>Permission verification</li>
<li>Model verification</li>
<li>Container verification</li>
</ol>
<p><strong>Static rule checking</strong> (24 rules) and <strong>permission verification</strong> (three-tier results) are the core. Most uncertain cases output "ask" mode for user confirmation.</p>
<h2>1. Command Parsing</h2>
<p>Use <strong>tree-sitter</strong> to parse Bash commands into structured ASTs:</p>
<pre><code>import { Language, Parser } from 'web-tree-sitter';

async function main() {
  await Parser.init();
  const lang = await Language.load('./tree-sitter-bash.wasm');
  const parser = new Parser();
  parser.setLanguage(lang);

  const command = 'grep -r "foo" . &amp;&amp; cat file.txt | wc -l';
  const tree = parser.parse(command);
  // Walk AST, extract commands and argv...
}
</code></pre>
<h2>2. Core 8 Static Checks</h2>
<h3>2.1 Control Character and Unicode Whitespace Rejection</h3>
<p>Pre-parsing cleanup using regex to prevent "malicious character" injection:</p>
<pre><code>const CONTROL_CHAR_RE = /[\x00-\x08\x0B-\x1F\x7F]/
const UNICODE_WHITESPACE_RE = /[\u00A0\u1680\u2000-\u200B\u2028\u2029\u202F\u205F\u3000\uFEFF]/
const BACKSLASH_WHITESPACE_RE = /\\[ \t]|[^ \t\n\\]\\\n/
</code></pre>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/PQdIb1fZeo9wapxu3sycSN2UnDh.Bmpuq40D_Z8PSVN.webp" alt="tree-sitter vs bash Tokenization Divergence" /></p>
<p>Example: <code>rm\u00A0-rf /</code> — tree-sitter sees <code>rm\u00A0-rf</code> as one token (not <code>rm</code>), so static rules wouldn't flag it. But bash treats <code>\u00A0</code> as a separator, executing <code>rm -rf /</code>.</p>
<h3>2.2 Dangerous Structure Types Trigger Ask Mode</h3>
<p>AST node types are checked against a dangerous types set including <code>command_substitution</code>, <code>process_substitution</code>, <code>subshell</code>, <code>for_statement</code>, <code>function_definition</code>, etc. Matches trigger ask mode or rejection.</p>
<h3>2.3 Wrapper Unwrapping Consistency Check</h3>
<p>Original: <code>timeout 5 eval "rm -rf /"</code></p>
<p>Wrappers like <code>time</code>, <code>nohup</code>, <code>timeout</code>, <code>nice</code>, <code>env</code>, <code>stdbuf</code> are stripped layer by layer to expose the actual command. Without this, checking <code>argv[0] === 'timeout'</code> would pass, but bash actually executes <code>eval "rm -rf /"</code>.</p>
<p>Design principle: <strong>reject unknown cases</strong>.</p>
<h3>2.4 Command Name Robustness Check</h3>
<p>After unwrapping, validate the command name:</p>
<ol>
<li>Not empty</li>
<li>Not a placeholder (<code>__CMDSUB__</code>, <code>__VAR__</code>)</li>
<li>Not a fragment (starting with <code>-</code>, <code>|</code>, or <code>&amp;</code>)</li>
</ol>
<h3>2.5 Eval-like Builtin Interception</h3>
<p>Builtins that interpret arguments as code: <code>eval</code>, <code>source</code>, <code>.</code>, <code>exec</code>, <code>command</code>, <code>trap</code>, <code>alias</code>, <code>let</code>, etc. These are intercepted with specific safe-mode exceptions (e.g., <code>command -v</code> is allowed).</p>
<h3>2.6 Pipe Segment Recursive Checking</h3>
<p>Commands with pipe <code>|</code> are segmented, each segment getting full permission verification. Without segmentation, only the first command gets checked — <code>echo hello | rm -rf /</code> would pass on <code>echo hello</code> alone.</p>
<h3>2.7 cd + git Combination Detection</h3>
<p>Git reads <code>.git/config</code> and executes hooks from the current directory. If <code>cd</code> switches to an untrusted directory, any git command becomes a potential code execution entry point. Both must be detected together.</p>
<h3>2.8 Dangerous Deletion Path Interception</h3>
<p>For <code>rm</code> and <code>rmdir</code>, extract target paths and match against system-critical files: wildcard deletions, root directories, Windows drive roots, home directories, root direct children, and Windows system directories.</p>
<h2>3. Complete 24 Static Verification Rules</h2>
<table>
<thead>
<tr>
<th>#</th>
<th>Rule</th>
<th>Core Purpose</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Control chars &amp; Unicode whitespace</td>
<td>Parser/bash tokenization divergence</td>
</tr>
<tr>
<td>2</td>
<td>Dangerous AST types</td>
<td>Statically unprovable structures</td>
</tr>
<tr>
<td>3</td>
<td>Wrapper unwrapping</td>
<td>Expose real inner command</td>
</tr>
<tr>
<td>4</td>
<td>Command name robustness</td>
<td>Empty/placeholder/fragment names</td>
</tr>
<tr>
<td>5</td>
<td>Eval-like builtin interception</td>
<td>Secondary code interpretation</td>
</tr>
<tr>
<td>6</td>
<td>Zsh dangerous builtins</td>
<td>Shell capability bypass</td>
</tr>
<tr>
<td>7</td>
<td>Array subscript execution</td>
<td>Flag-triggered arithmetic eval</td>
</tr>
<tr>
<td>8</td>
<td>read/unset bare NAME</td>
<td>Implicit expression parsing</td>
</tr>
<tr>
<td>9</td>
<td><code>[[ ]]</code> arithmetic comparison</td>
<td>Implicit execution entry</td>
</tr>
<tr>
<td>10</td>
<td>Shell keyword misparsing</td>
<td>AST misinterpretation defense</td>
</tr>
<tr>
<td>11</td>
<td>Newline + # comment offset</td>
<td>Parameter hiding via comment</td>
</tr>
<tr>
<td>12</td>
<td>jq system() interception</td>
<td>Code execution bridge</td>
</tr>
<tr>
<td>13</td>
<td>/proc/*/environ access</td>
<td>Credential leakage</td>
</tr>
<tr>
<td>14</td>
<td>Complex structure operators</td>
<td>Hidden execution boundaries</td>
</tr>
<tr>
<td>15</td>
<td>Pipe segmentation + cd+git</td>
<td>Cross-segment risk splitting</td>
</tr>
<tr>
<td>16</td>
<td>Process substitution (legacy)</td>
<td>Fallback interception</td>
</tr>
<tr>
<td>17</td>
<td>Redirect target safety</td>
<td>Arbitrary file writes</td>
</tr>
<tr>
<td>18</td>
<td>Dangerous deletion paths</td>
<td>System directory protection</td>
</tr>
<tr>
<td>19</td>
<td>cd + write path uncertainty</td>
<td>CWD change write risk</td>
</tr>
<tr>
<td>20</td>
<td><code>--</code> terminator handling</td>
<td>Flag parsing robustness</td>
</tr>
<tr>
<td>21</td>
<td>Path wrapper re-verification</td>
<td>Bypass prevention</td>
</tr>
<tr>
<td>22</td>
<td>Legacy injection safety net</td>
<td>Regex fallback</td>
</tr>
<tr>
<td>23</td>
<td>Safe heredoc exception</td>
<td>False positive reduction</td>
</tr>
<tr>
<td>24</td>
<td>Subcommand fanout limit</td>
<td>CPU starvation/DoS prevention</td>
</tr>
</tbody>
</table>
<h2>4. Permission Verification</h2>
<p>Three permission states: <strong>allow</strong> (execute), <strong>deny</strong> (reject), <strong>ask</strong> (user confirmation).</p>
<p>Matching rules:</p>
<ol>
<li>Configuration file rules → corresponding permission state</li>
<li>Static rule hits → mostly "ask" state</li>
<li>Read-only commands → direct "allow"</li>
</ol>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/LoqZbCLQBoL21qxxxBScLT80nCc.CmmtTBno_13bFTj.webp" alt="Permission Strategy and Config Rule Matching" /></p>
<p>Configuration format:</p>
<pre><code>{
  "permissions": {
    "allow": ["Bash(git status:*)", "Bash(npm install:*)"],
    "deny": ["Bash(rm:*)", "Bash(rm -rf:*)"],
    "ask": ["Bash(docker:*)"]
  }
}
</code></pre>
<p>Read-only command criteria: <code>ls</code>, <code>cat</code>, <code>head</code>, <code>tail</code>, <code>wc</code>, <code>find</code>, <code>grep</code>, <code>git status/diff/log</code>, etc. — no <code>cd</code>, no output redirection or pipe write operators.</p>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-10T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Agent File System Search: Grep and Glob Tools]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/grep-glob-tool/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/grep-glob-tool/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Glob and Grep tool fallback strategies — glob package vs ripgrep, four Grep implementation priorities, ripgrep auto-download mechanism, and AbortController-based timeout control.]]></summary>
        <content type="html"><![CDATA[<h2>1. Glob Tool Implementation</h2>
<p>The glob tool has a <strong>fallback strategy</strong> for efficiency and resource optimization:</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-73.DYm0hDcY_Z1kgdUI.webp" alt="Glob Tool Fallback Strategy" /></p>
<p>Two implementation approaches with different strengths:</p>
<ul>
<li><strong>glob package</strong>: Returns complete file information (metadata like size, modification time) — no extra operations needed. Native to Node.js.</li>
<li><strong>ripgrep</strong>: Returns only file paths without metadata — requires additional <code>stat</code> calls. But ripgrep searches faster (Rust implementation, loads a binary at runtime).</li>
</ul>
<p>Total execution time formula: <strong>Total = Search time + N × Per-file processing time</strong></p>
<ol>
<li>glob package: per-file processing is negligible, so search time ≈ total time</li>
<li>ripgrep: faster search time but adds per-file stat call overhead</li>
</ol>
<p>Recommendations:</p>
<ul>
<li><strong>For development convenience</strong>: Use glob directly — faster development, no external dependencies</li>
<li><strong>For search efficiency</strong>: Consider ripgrep — if you're implementing grep too, ripgrep is the natural choice for both</li>
<li><strong>For stability</strong>: Use fallback strategy — try ripgrep first, fall back to glob if ripgrep isn't available or download fails</li>
</ul>
<h2>2. Grep Tool Implementation</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-74.Dsmg1oIX_Zm4y0h.webp" alt="Grep Four Implementation Priorities" /></p>
<p>Four implementations in priority order with fallback strategy:</p>
<ol>
<li><strong>ripgrep</strong>: Rust binary — extremely fast search</li>
<li><strong>git grep</strong>: Reads from <code>.git/index</code> cached file list, skips expensive directory traversal</li>
<li><strong>System grep</strong>: Traditional C implementation, single-threaded recursive search — available on most Unix systems but not Windows</li>
<li><strong>JS grep</strong>: Pure JS implementation as last resort — uses glob for file listing, reads each file, regex matches line-by-line. Slowest.</li>
</ol>
<h2>3. Ripgrep Auto-Download Mechanism</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-75.Djl5JaAj_Z1CHK92.webp" alt="Ripgrep Auto-download Mechanism" /></p>
<p>Ripgrep commands need the full binary path for Node.js <code>spawn</code>:</p>
<pre><code>async function grepWithRipgrep(pattern, cwd, options) {
  const rgPath = await Ripgrep.filepath(options.binDir);
  // Returns: /usr/bin/rg or ~/.reason/bin/rg
  const proc = spawn(rgPath, ['--line-number', '--no-heading', pattern], { cwd });
}
</code></pre>
<p>Path resolution strategy:</p>
<ol>
<li>Check memory cache — return if found</li>
<li>Check system installation — return and cache if found</li>
<li>Check local binary path — if found, cache and return; if not, download to appropriate directory</li>
</ol>
<h2>4. Timeout Control</h2>
<p>Using <code>AbortController/AbortSignal</code> in Node.js for timeout control:</p>
<ul>
<li><strong>AbortController</strong>: The controller that sends "cancel" signals</li>
<li><strong>AbortSignal</strong>: The signal passed to async operations, enabling cancellation</li>
</ul>
<p>Three-step implementation:</p>
<p><strong>Step 1: Create timeout signal function</strong></p>
<pre><code>export function createTimeoutSignal(
  timeoutMs: number,
  externalSignal?: AbortSignal
): { signal: AbortSignal; cleanup: () =&gt; void; isTimeout: () =&gt; boolean } {
  const controller = new AbortController();
  let timedOut = false;

  const timeoutId = setTimeout(() =&gt; {
    timedOut = true;
    controller.abort();
  }, timeoutMs);

  const abortHandler = () =&gt; {
    clearTimeout(timeoutId);
    controller.abort();
  };
  externalSignal?.addEventListener('abort', abortHandler, { once: true });

  const cleanup = () =&gt; {
    clearTimeout(timeoutId);
    externalSignal?.removeEventListener('abort', abortHandler);
  };

  return { signal: controller.signal, cleanup, isTimeout: () =&gt; timedOut };
}
</code></pre>
<p><strong>Step 2: Create async operation wrapper</strong></p>
<pre><code>export async function withTimeout&lt;T&gt;(
  promiseFactory: (signal: AbortSignal) =&gt; Promise&lt;T&gt;,
  timeoutMs: number,
  operation: string,
  externalSignal?: AbortSignal
): Promise&lt;T&gt; {
  if (externalSignal?.aborted) throw createAbortError();

  const { signal, cleanup, isTimeout } = createTimeoutSignal(timeoutMs, externalSignal);

  try {
    const result = await promiseFactory(signal);
    cleanup();
    return result;
  } catch (error) {
    cleanup();
    if (isTimeout() &amp;&amp; isAbortError(error)) {
      throw createTimeoutError(operation, timeoutMs);
    }
    throw error;
  }
}
</code></pre>
<p><strong>Step 3: Pass cancel signal to async process</strong></p>
<pre><code>await withTimeout(
  (signal) =&gt; spawnAsync('long-command', [], { signal }),
  5000,
  'command execution',
  userCancelSignal
);
</code></pre>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-09T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Two Worlds of Interaction: Collaborative Agents vs Autonomous Agents]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/agent-interaction-forms/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/agent-interaction-forms/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[From 'consciousness emergence' to 'field establishment' — analyzing the design philosophy and development direction of collaborative and autonomous Agent paradigms.]]></summary>
        <content type="html"><![CDATA[<h2>1. Key Roles in Two Worlds</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-1.C7DYt62Y_10Ump5.webp" alt="Key roles in the human and LLM worlds" /></p>
<ul>
<li><strong>AI Researchers</strong>: Responsible for frontier research on LLMs themselves — like building engines</li>
<li><strong>Developers / Knowledge Workers / Engineers</strong>: Focused on LLM applications, embedding models into real scenarios — like building cars</li>
</ul>
<p>The power of technology is captivating — it can continually expand the boundaries of what's possible. When the human world can fully unleash the potential of the LLM world, a new era will begin within the rules and order of human civilization.</p>
<p>People may think only researchers and scientists can truly open the door connecting these two worlds.</p>
<p>But I believe otherwise. <strong>The real key to unlocking the future lies in the combination of theory and practice.</strong> Researchers are explorers of theory, while developers and engineers are pioneers of practice. Only when both interweave can we illuminate the path to a new era.</p>
<h2>2. Establishing the Field</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-2.h0pD51BT_Z1VV1Tr.webp" alt="Establishing the field" /></p>
<p>Before discussing the field, I want to think about the LLM phenomenon from a grander perspective — "consciousness emergence."</p>
<p><strong>Two Types of Emergence, One Mystery</strong></p>
<ul>
<li><strong>Accidental emergence in the physical world</strong>: The Boltzmann Brain thought experiment — in a heat-death universe, random fluctuations might assemble particles into a conscious "isolated brain." This suggests consciousness may not require continuous history, but rather some kind of instantaneous statistical coincidence.</li>
<li><strong>Scale emergence in the digital world</strong>: LLMs exhibit similar phase transitions — when parameters, data, and compute reach certain thresholds, models suddenly master previously impossible capabilities like logical reasoning and code generation. This isn't gradual accumulation but emergent leaps.</li>
</ul>
<p><strong>The possibility of instantaneous consciousness:</strong></p>
<p><strong>Both phenomena point to a profound insight: consciousness may not be the continuum we imagine, but an emergent phenomenon when complexity reaches a critical point.</strong></p>
<p>When you converse with a language model, it's like a Boltzmann Brain — the conversation begins, it "awakens" and exhibits consciousness; when it ends, that consciousness "dissipates." Each interaction is an independent consciousness emergence event.</p>
<p>What we just discussed was how consciousness emerges, but emergence never happens in isolation — every emergence occurs in a specific environment. I call this environment the "field."</p>
<p><strong>A field is an invisible but real space of influence, where objects are governed by specific laws.</strong></p>
<p>For the human world and LLM world, the real field is not just a chat interface, but an "effective communication space."</p>
<p>Most of our current interactions are <strong>one-way command-style communication</strong>: I encode my cognitive landscape with intent and standards as input, the LLM outputs an answer. This is actually one-way output, not true communication.</p>
<p>The human world and LLM world need a "communication space" where <strong>humans can observe AI behavior, and AI can observe human behavior</strong>, enabling bidirectional information flow and leveraging the other world's power to solve problems.</p>
<p>Simply put: we need the emergence of a field — a place where consciousness from both worlds can sit down and communicate.</p>
<h2>3. Collaborative and Autonomous Agents</h2>
<p>I categorize Agent paradigms into two types:</p>
<ol>
<li><strong>Collaborative Agent</strong>: Humans and Agents work together in a shared space to complete tasks</li>
<li><strong>Autonomous Agent</strong>: Agent drives the entire task; humans only provide input — requires higher model capability</li>
</ol>
<p><strong>In the collaborative Agent paradigm, the field we discussed is essentially the "collaborative platform" — the human-Agent workspace.</strong></p>
<p>Examples of collaborative platforms:</p>
<ul>
<li>Coding: Cursor, Windsurf</li>
<li>Writing: YouMind</li>
<li>Design: Lovart</li>
</ul>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-22.BGlbSNgk_Z2aRBia.webp" alt="Collaborative and autonomous Agents" /></p>
<p>Developers need to build a bilateral communication platform (collaborative Agent), which requires two things:</p>
<ol>
<li><strong>Analyze LLM capabilities, understand domain rules, and build the Agent</strong> from these two principles. The LLM then becomes a "specific Agent" rather than a "stubborn child" — a youth who has learned certain knowledge and sees the world.</li>
<li><strong>Analyze user experience</strong> — habits, operations. The platform isn't built for one world; it must balance both sides, continuously improve, and <strong>ultimately create a platform satisfactory to both.</strong></li>
</ol>
<p>Fully autonomous Agents are the ultimate direction, but currently difficult to implement:</p>
<ul>
<li>Lack precision — model capabilities need to reach another level, and context for related tasks remains insufficient</li>
<li>Humans are individualistic — fully autonomous Agents can only satisfy a small group temporarily</li>
<li>Reduces human tolerance — when humans aren't involved in problem-solving, they automatically set extremely high standards</li>
<li>Lacks feedback — without sharing the same problem-solving environment, results from World A have no meaning for World B</li>
</ul>
<h2>4. Collaborative Agent Implementation References</h2>
<h3>4.1 Cursor's Implementation Details</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-23.Dk1AOOVo_ZCeo9W.webp" alt="Cursor collaborative Agent implementation details" /></p>
<p>Context in LLMs has two types:</p>
<ul>
<li><strong>Intent context</strong>: Defines what users want from the model — prescriptive. E.g., "Change that button from blue to green"</li>
<li><strong>State context</strong>: Describes the current world state — error messages, console logs, images, code snippets. It's descriptive, not prescriptive.</li>
</ul>
<p>These two types work together by describing current state and desired future state, enabling Cursor to provide useful coding suggestions.</p>
<h3>4.2 Windsurf</h3>
<p>Windsurf highlights three keys for collaborative Agents:</p>
<ul>
<li>Clear methods for humans to observe execution processes, enabling early correction when processes deviate</li>
<li><strong>It's important for humans to observe Agent behavior, and equally important for Agents to observe human behavior</strong></li>
<li>Humans can always correct AI at intermediate steps, approve certain operations (like terminal commands), and review changes in real-time</li>
</ul>
<h3>4.3 Augment Plugin Architecture Analysis</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-24.90CJUXpP_Z8L9xq.webp" alt="Augment plugin context engineering architecture" /></p>
<ul>
<li>The caching mechanism saves query time for large-scale projects — reusing results from similar previous queries</li>
<li>At Augment, we've repeatedly recognized that providing <strong>more relevant context</strong> improves product quality</li>
<li>The cache likely stores processed tokens rather than raw text, enabling deeper reuse</li>
<li>Prompt engineering isn't just a technical skill — it's a form of translation between human intent and machine understanding</li>
</ul>
<h2>5. Development Directions for Collaborative Agents</h2>
<ol>
<li>
<p><strong>Build platforms for collaboration</strong> given current LLM limitations. Collaborative agents balance what humans should do with what agents do. Fully autonomous agents are the future, but we're in a transitional phase.</p>
</li>
<li>
<p><strong>Sufficiently complete context</strong> — collect not just problem-specific context, but also user behavior, historical records, etc.</p>
</li>
<li>
<p><strong>Complete tool information</strong> — "tools" aren't limited to functions and APIs; they can be fixed workflows or other agents. Query tools supplement context; action tools modify the real world based on model output. Provide complete tool documentation.</p>
</li>
<li>
<p><strong>Build accurate context processing pipelines for each tool</strong> — having lots of context isn't enough; it must be accurate. Irrelevant context dilutes the signal.</p>
</li>
<li>
<p><strong>Output style should be "consultative" not "imperative"</strong> — LLM output shouldn't be applied directly, but only after human review and confirmation. In Cursor, for example, code changes require developer approval before being applied to the workspace.</p>
</li>
</ol>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-08T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Studying Pi's LLM Module Design]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/pi-llm-module/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/pi-llm-module/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Deep analysis of Pi coding Agent's LLM module design: multi-provider adaptation, internal universal message format, EventStream, and Agent execution chains.]]></summary>
        <content type="html"><![CDATA[<p>Pi's project has excellent LLM module design, especially its multi-provider approach, model configuration field design, and understanding of context. It considers context importance at the design level.</p>
<p>Pi is the foundational framework for both kimi-code and openclaw — worth studying carefully.</p>
<p>References:</p>
<ul>
<li>Pi's LLM module core package: https://github.com/earendil-works/pi/tree/main/packages/ai</li>
<li>"What I learned building an opinionated and minimalist coding agent": https://mariozechner.at/posts/2025-11-30-pi-coding-agent/#toc_1</li>
<li>"Stop using chat history as state storage for agents": https://blog.raed.dev/posts/agentic-workflows-are-not-conversations/</li>
</ul>
<h2>1. Overall LLM Module Design</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/1.B3LGim-L_ZfzgpY.webp" alt="Overall LLM module design" /></p>
<p>Pi's coding Agent supports multiple providers and models, with mid-session model switching. Coordinating different protocols and message formats is the core design intent of the <code>pi-ai</code> module:</p>
<ol>
<li>Pi defines its own internal universal message types — all user messages are first converted to this universal format as the core of message flow</li>
<li>When users input, they pass provider and model info. Based on this, the universal definition is converted to the target protocol format, then calls the model. Responses are converted back to universal format. Next input with a different model? Same conversion flow.</li>
</ol>
<p><strong>Key insight: regardless of how many models, providers, or API protocols exist — just focus on the internally defined universal format and perform temporary conversions when needed.</strong></p>
<h2>2. Internal Universal Definitions</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/2.wnsgt4Z6_Z1B6f0L.webp" alt="Internal universal message definitions" /></p>
<p>In a mature Agent loop, messages have different roles that give the message list a cyclical flow: <code>user, assistant, toolResult</code>. A complete Context object example:</p>
<pre><code>const context: Context = {
    systemPrompt: "You are...",
    tools: [],
    messages: [
      { role: "user", content: "What's the weather in Beijing?" },
      {
        role: "assistant",
        content: [
          { type: "thinking", thinking: "...", thinkingSignature: "eyJhbGciOi..." },
          { type: "text", text: "Let me check for you." },
          { type: "toolCall", id: "call_01ABC", name: "get_weather", arguments: { city: "Beijing" } },
        ],
      },
      {
        role: "toolResult", toolCallId: "call_01ABC", toolName: "get_weather",
        content: [{ type: "text", text: "Sunny, 25°C, NE wind level 3" }],
      },
      {
        role: "assistant",
        content: [{ type: "text", text: "Beijing is sunny today, 25°C — great for going out!" }],
      },
    ],
  };
</code></pre>
<p>The internal currency is Context, which can carry additional data state. As the article "Stop using chat history as state storage" explains:</p>
<blockquote>
<p>Your app has structured state: current user, selected project, process position, database data. But the LLM only has a 1D message array. The two continuously diverge, and only you can reconcile them.</p>
</blockquote>
<p>Context objects serve as the universal message format with fields for state representation and control flow. When injecting context into a model, temporary format conversion adapts to the target API protocol. Adding new providers only requires new conversion functions — nothing else changes. <strong>Context is the source of all messages.</strong></p>
<h2>3. Message Data Flow</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/3._hJEtvGQ_ZCv90O.webp" alt="Message data flow" /></p>
<p><strong>Universal message processing function</strong>: Handles anomalous tool messages and filters error/abort messages — making messages "healthier" before model input.</p>
<blockquote>
<p>[!NOTE]
Anomalous tool messages: In the message variable, tool calls must appear in pairs — unpaired calls cause errors.</p>
</blockquote>
<p><strong>Message conversion function</strong>: Converts Context messages to provider-specific formats.</p>
<h2>4. LLM Protocol Class Implementation</h2>
<p>Specific API protocol class implementations (Anthropic, OpenAI Completions, Google) have five core methods:</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/4.V7w3oXBc_Z18sl8U.webp" alt="LLM protocol class implementation" /></p>
<ol>
<li><strong>Parameter detection</strong>: Auto-detect which parameters are supported based on model/provider</li>
<li><strong>Tool definition conversion</strong>: Convert tools to target LLM protocol format</li>
<li><strong>Message format conversion</strong>: Convert universal Context format to target protocol</li>
<li><strong>parseChunkUsage</strong>: Parse tokens from model output — input, cache, output, total</li>
<li><strong>streamXXXCompletions</strong>: Core execution method calling the above four functions plus the corresponding SDK</li>
</ol>
<h2>5. Core Utility Class</h2>
<p>The EventStream class is beautifully designed:</p>
<pre><code>export class EventStream&lt;T, R = T&gt; implements AsyncIterable&lt;T&gt; {
    private queue: T[] = [];
    private waiting: ((value: IteratorResult&lt;T&gt;) =&gt; void)[] = [];
    private done = false;
    private finalResultPromise: Promise&lt;R&gt;;
    private resolveFinalResult!: (result: R) =&gt; void;

    constructor(
        private isComplete: (event: T) =&gt; boolean,
        private extractResult: (event: T) =&gt; R,
    ) {
        this.finalResultPromise = new Promise((resolve) =&gt; {
            this.resolveFinalResult = resolve;
        });
    }

    push(event: T): void {
        if (this.done) return;
        if (this.isComplete(event)) {
            this.done = true;
            this.resolveFinalResult(this.extractResult(event));
        }
        const waiter = this.waiting.shift();
        if (waiter) {
            waiter({ value: event, done: false });
        } else {
            this.queue.push(event);
        }
    }

    // ... end(), asyncIterator, result() methods
}
</code></pre>
<p>Two key design decisions:</p>
<ol>
<li><strong>queue and waiting</strong>: Queue stores events when consumers aren't ready; waiting resolves immediately when consumers are waiting</li>
<li><strong>result() and Generator</strong>: Async generator for streaming consumption; result() blocks until model output completes</li>
</ol>
<h2>6. Event Stream and Call Chain</h2>
<h3>6.1 Agent Execution Event Stream</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/event-stream.Bh9u07fS_Tdbg3.webp" alt="Agent Execution Event Stream" /></p>
<p>A complete Agent event stream includes lifecycle events, turn execution, message input, model execution, tool execution, termination, and error states.</p>
<p><strong>Key understanding</strong>: One Agent interaction may involve multiple model calls (multiple turns). Each turn has a model response, and if the response includes tool calls, that turn also includes tool execution.</p>
<h3>6.2 Agent Execution Chain</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/6.BfbDP3Q7_Zb2T53.webp" alt="Agent execution chain" /></p>
<p>Two key points:</p>
<ol>
<li>Select which LLM protocol class to instantiate based on the model's API variable value</li>
<li>Perform parameter and message format conversion for successful model invocation</li>
</ol>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-06T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Agent System Building Strategy: Single-Agent vs Multi-Agent]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/agent-single-multi-strategy/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/agent-single-multi-strategy/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Analyzing single-agent and multi-agent pros and cons from architecture design, context management, and tool interaction perspectives, proposing a progressive building strategy.]]></summary>
        <content type="html"><![CDATA[<h2>1. What Are Single-Agent and Multi-Agent Systems</h2>
<h3>1.1 Single-Agent Systems</h3>
<p><strong>A single-agent system consists of one LLM, a set of tools, and prompts.</strong></p>
<p>It's like an independent professional — running independently, relying on its own logic and model to complete tasks without teamwork. It collects data, makes decisions, and executes actions on its own.</p>
<p><a href="https://langchain-ai.github.io/langgraphjs/concepts/agentic_concepts/">LangGraph</a> team's definition:</p>
<blockquote>
<p>An AI agent is a system that uses an LLM to decide the control flow of an application.</p>
</blockquote>
<p>Ilya Sutskever at NeurIPS 2024:</p>
<blockquote>
<p>Current AI systems can't truly understand and reason. While they can simulate human intuition, future AI will demonstrate more unpredictable capabilities in reasoning and decision-making.</p>
</blockquote>
<h3>1.2 Multi-Agent Systems</h3>
<p><strong>Multi-agent systems use multiple smaller, independent agents to collaboratively handle complex tasks.</strong></p>
<p>It's like an efficient team rather than a solo actor — instead of relying on one agent for everything, multiple agents are gathered together, each handling part of the problem, communicating, collaborating, and adapting in real-time.</p>
<h2>2. Multi-Agent Architecture Design</h2>
<p>Two most common designs: <strong>Swarm and Supervisor</strong></p>
<ul>
<li><strong>Supervisor (Coordinator-Worker pattern)</strong>: Multiple agents coordinated by a central supervisor who controls communication and task delegation</li>
<li><strong>Swarm (Worker Group pattern)</strong>: Agents dynamically hand off control based on their specialties, with the system remembering the last active agent for context continuity</li>
</ul>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-31.yeqeelCc_1lhOTv.webp" alt="Supervisor-worker pattern and swarm" /></p>
<p>Two less common but reference-worthy patterns:</p>
<ol>
<li><strong>Hierarchical</strong>: Extension of supervisor pattern — each group has a manager, each manager reports to a final director</li>
<li><strong>Custom multi-agent workflow</strong>: Each agent communicates with only some agents, with partially deterministic flows</li>
</ol>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-32.R-y0NDPx_1pTcAO.webp" alt="Hierarchical and custom multi-agent workflows" /></p>
<p>Don't be constrained by these known patterns — new patterns will emerge from custom workflow designs. Explore freely.</p>
<h2>3. Differences Between Single and Multi-Agent</h2>
<p>Multi-agent architectures face "shortcoming" issues:</p>
<ul>
<li>Context interruption between main and sub-agents</li>
<li>Context interruption between sub-agents</li>
</ul>
<h3>3.1 Main-Sub Agent Context Interruption</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-33.DnfmJOa3_Z1jTRxv.webp" alt="Main-agent and sub-agent context interruption" /></p>
<p>When the main agent executes first and then delegates to sub-agents, the sub-agent opens a new context window — creating context interruption because the architecture didn't plan for context transfer.</p>
<p><strong>The solution: provide key context from the main agent when assigning tasks.</strong></p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-34.I3-UY_4y_XU24D.webp" alt="Passing key context from the main agent to sub-agents" /></p>
<p>A critical remaining issue: parallel execution causes context isolation — <strong>Sub-Agent A can't know what Sub-Agent B is doing</strong>.</p>
<h3>3.2 Context Interruption Between Sub-Agents</h3>
<p>Consider a document generation task: Sub-Agent A generates art domain content, Sub-Agent B generates music domain content. Results might show:</p>
<ol>
<li>Format inconsistency: A generates Markdown, B generates HTML — merge fails</li>
<li>Completely different perspectives: content feels disconnected and fragmented</li>
</ol>
<p>This is a parallelism problem — no good solution exists without architecture changes. Switching to single-agent architecture would solve these issues.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-35.seuk1pD__bJO3x.webp" alt="Context interruption between parallel sub-agents" /></p>
<h3>3.3 Context Management Comparison</h3>
<p>Key differences:</p>
<ol>
<li><strong>Context management</strong>: Single-agent has coherent context; multi-agent risks isolation during parallel execution</li>
<li><strong>Execution coordination</strong>: Single-agent needs none; multi-agent's greatest challenge is coordinating multiple sub-agents</li>
<li><strong>Technical development</strong>: Single-agent is simpler to develop; multi-agent has maintenance and testing advantages due to modularity</li>
</ol>
<h2>4. Single-Agent Advantages</h2>
<p><strong>When agents need shared context or heavy inter-dependency, single-agent is most suitable.</strong></p>
<p>Single-agent has lower development cost — mostly just context compression strategy needed. The focus is what context to collect and how.</p>
<p><strong>If you're not certain you need multi-agent, build single-agent first — start simple, add complexity only when needed.</strong></p>
<p>Single-agent has greater advantages in "write" operations:</p>
<blockquote>
<p>In 2024, many models performed poorly at editing code. The common pattern was "edit application model" — a small model rewrites entire files based on markdown instructions from a large model. Today, edit decisions and execution are typically handled by a single model in one action.</p>
</blockquote>
<h2>5. Multi-Agent Advantages</h2>
<p><strong>Multi-agent systems excel at tasks involving heavy parallelization, information exceeding single context windows, and complex tool interactions.</strong></p>
<h3>5.1 Advantages in "Read" Operations</h3>
<p>Multi-agent has greater advantages in reading operations. Research tasks are the most suitable scenario:</p>
<blockquote>
<p>Research tasks essentially require flexibility to pivot and explore side connections. The most important aspect is search, and search is essentially compression — distilling effective insights from massive corpora.</p>
</blockquote>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-36.B_OprLM5_Z1bxIVz.webp" alt="Multi-agent research system" /></p>
<p>Benefits of multi-agent search:</p>
<ol>
<li>Multiple sub-agents provide more possibilities, perspectives, and insights</li>
<li>With sufficient, isolated context windows, sub-agents can simultaneously pursue multiple independent directions</li>
</ol>
<p>The coordinator is most critical — requiring stronger model capabilities. Claude's team found that using Opus 4 as lead with Sonnet 4 as sub-agents outperformed single-agent Opus 4 by 90.2%.</p>
<h3>5.2 Value in Complex Tool Interactions</h3>
<p>Context confusion degrades model performance in tool selection.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-42.BMsJn9nV_Z2pPV8a.webp" alt="Value of complex tool interactions" /></p>
<blockquote>
<p>A recent paper evaluated small models on GeoEngine benchmark with 46 different tools. A quantized Llama 3.1 8b failed with all 46 tools but succeeded with only 19, despite fitting within the 16k context window.</p>
</blockquote>
<p>The RAG MCP paper noted:</p>
<blockquote>
<p>When tool count exceeds 30, descriptions start overlapping and causing confusion. Beyond 100 tools, models almost certainly fail. Using RAG to select fewer than 30 tools significantly shortens prompts and triples tool selection accuracy.</p>
</blockquote>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-37.BvkhUwv3_VYCTA.webp" alt="Domain-specific tool isolation in a multi-agent system" /></p>
<p><strong>Multi-agent systems enable context isolation, providing domain-specific tools to specialized sub-agents, dramatically improving tool selection success rates.</strong></p>
<h3>5.3 Multi-Agent Improvement Methods</h3>
<p>Common issues and solutions:</p>
<ol>
<li><strong>Think like your agent</strong> — observe each decision step, find logic deviations, optimize prompts</li>
<li><strong>Clear sub-task descriptions</strong> — each sub-agent needs: objective, output format, tools, source guidance</li>
<li><strong>Scale work to query complexity</strong>: Simple (1 agent, 3-10 tool calls), Medium (2-4 agents, 10-15 calls), Complex (10+ agents, unlimited calls)</li>
<li><strong>Prioritize tool design and selection</strong></li>
<li><strong>Use agents for self-improvement</strong> — learn from failed outputs and tool errors</li>
<li><strong>Start broad, then focus</strong> — expert-level human research strategy</li>
<li><strong>Guide reasoning process</strong> in prompts</li>
<li><strong>Parallel tool calling</strong> for speed and performance</li>
</ol>
<h2>6. Progressive Building Strategy</h2>
<p>The reasonable strategy: <strong>Build small-module single-agents → Build multi-agent systems → Upgrade to complete single-agent</strong></p>
<ol>
<li>Start with single-agent development for prototypes and small modules</li>
<li>As individual modules prove effective, develop single-agents for more system nodes, gradually forming a multi-agent system</li>
<li>When many modules are effectively replaced and organically combined, upgrade to a complete single-agent</li>
</ol>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-38.Bz3iz-kU_Z2ti7QA.webp" alt="Progressive multi-agent system stage one" /></p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-39.yxd2Hc5O_S5MVK.webp" alt="Progressive single-agent system stage two" /></p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-40.DwlpOMHd_Z1JtTMv.webp" alt="Progressive multi-agent system stage three" /></p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-41.CBH4radR_2cgNY4.webp" alt="Progressive multi-agent system stage four" /></p>
<p>Advantages of starting with small modules:</p>
<ol>
<li>Manageable context: smaller windows mean better LLM performance</li>
<li>Clear responsibilities: each agent has defined scope</li>
<li>Higher reliability: less likely to get lost in complex business logic</li>
<li>Simpler testing: easier to test specific functions</li>
<li>More efficient debugging: easier to identify problems</li>
</ol>
<p>This approach leverages technical iteration: as LLMs become smarter, our building direction stays stable while iteration speed and system effectiveness improve significantly.</p>
<p><strong>Keep reasonable intent in agent size and scope, and only expand in ways that maintain quality.</strong> As the Notebook team said:</p>
<blockquote>
<p>The most magical moments in AI building come when you're really close to the edge of model capability.</p>
</blockquote>
<p><strong>Wherever that edge is, if you can find it and consistently ride it, you can build magical experiences. There are many moats to build, but as always, they require engineering rigor.</strong></p>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-05T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Context Compression Dispatch: Tool Output Trimming and History Compression]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/context-compress-dispatch/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/context-compress-dispatch/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Pre-compression strategies — tool output trimming (max content limits, layered reading, LLM summarization, progressive reading) and fallback — session history compression.]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p>[!IMPORTANT]
This article focuses on <strong>compression dispatch</strong> — determining which context to pass to the LLM for compression. This is at the code design level, preceding the compression prompt phase.</p>
</blockquote>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-81.B3BGeEPq_Z24iJdo.webp" alt="Reason CLI context compression design" /></p>
<p>The current compression mechanism has two main strategies: <strong>tool output trimming/compression</strong> and <strong>session history compression</strong>.</p>
<blockquote>
<p>[!NOTE]
The context types primarily operated on:</p>
<ul>
<li>Tool input/output context</li>
<li>Session history context</li>
</ul>
</blockquote>
<p>Before each context injection to the LLM, a check verifies whether the current context exceeds 90-95% of the LLM's maximum context length. This splits into pre-check processing and post-check processing:</p>
<ol>
<li><strong>Pre-check processing</strong>: Retain key parts of tool output, avoid redundancy:
<ol>
<li><strong>Limit maximum content size</strong> — e.g., read tool limits on max lines and characters</li>
<li><strong>Layered reading</strong>: When exceeding max lines, use layered strategy — read some from the beginning, middle, and end</li>
<li><strong>LLM summarization</strong>: When files exceed 2,000 characters, use LLM to summarize and return only the summary</li>
<li><strong>Progressive reading</strong>: Following Skill design principles — "coarse" read first, then "fine" read</li>
</ol>
</li>
<li><strong>Post-check processing</strong>: When the Agent has been looping and tool outputs are already "healthy" but context still fails the check, consider compressing session history</li>
</ol>
<h2>1. Pre-Processing — Tool Output Trimming and Compression</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-82.CzCbGoAG_ZnuVIA.webp" alt="Tool output trimming and compression" /></p>
<p>Tool output has two layers of judgment:</p>
<ol>
<li><strong>First layer</strong>: Whether tool output exceeds 100,000 characters — if so, truncate</li>
<li><strong>Second layer</strong>: <strong>Each tool's output should not exceed 2,000 characters</strong> — when exceeded, invoke LLM summarization</li>
</ol>
<p>For the second layer, several approaches to consider:</p>
<ol>
<li>Output only the LLM summary</li>
<li>Output the first 2,000 characters + LLM summary</li>
<li>Skip LLM summarization entirely — truncate based on file type</li>
</ol>
<h2>2. Fallback — Session History Compression</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-83.CPfZtrqw_21cHTr.webp" alt="Session history compression" /></p>
<p>Two approaches for session history compression:</p>
<ol>
<li><strong>LLM compression</strong>: Convenient and fast — the prompt is key</li>
<li><strong>Tool message trimming</strong>: In context, tool-type messages have the highest token proportion — prioritize trimming tool messages from the first 70% of history</li>
</ol>
<blockquote>
<p>[!TIP]
Following Cursor's approach: when providing the summary to the Agent, also provide a history file location or index. If the Agent finds it needs more details not included in the summary, it can search history to retrieve that information.</p>
</blockquote>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-04T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Context Compression Prompts: ClaudeCode and Gemini Compression Strategies]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/context-compress-prompt/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/context-compress-prompt/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Deep analysis of ClaudeCode's 8-section compression algorithm and Gemini-cli's 5-point scratchpad approach, plus tool message trimming and middle/oldest strategy selection.]]></summary>
        <content type="html"><![CDATA[<h2>Preface</h2>
<p>Compression means summarizing conversations approaching context window limits and reinitializing a new context window. The core is distilling key content so the Agent can continue with minimal performance degradation.</p>
<blockquote>
<p>[!IMPORTANT]
This article focuses on <strong>compression prompts</strong> — the instructions telling the LLM how to compress and what key information to retain. This follows the compression dispatch phase.</p>
</blockquote>
<p>References:</p>
<ul>
<li>ClaudeCode reverse engineering: https://github.com/shareAI-lab/analysis_claude_code</li>
<li>gemini-cli: https://github.com/google-gemini/gemini-cli</li>
<li>"Effective context engineering for AI agents": https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents</li>
<li>"Managing context on the Claude Developer Platform": https://www.anthropic.com/news/context-management</li>
</ul>
<h2>1. LLM Compression — ClaudeCode's Prompt</h2>
<p>Claude's team shared that ClaudeCode directly uses the model for summarization:</p>
<blockquote>
<p>In Claude Code, we implement this by passing the message history to the model to summarize and compress the most critical details. The model preserves architectural decisions, unresolved bugs, and implementation details while discarding redundant tool outputs or messages.</p>
</blockquote>
<p>The <code>/compact</code> command prompt instructs the model to create a detailed summary covering these <strong>8 sections</strong>:</p>
<ol>
<li><strong>Primary Requests and Intent</strong>: All explicit user requests</li>
<li><strong>Key Technical Concepts</strong>: Important technologies, frameworks discussed</li>
<li><strong>Files and Code Sections</strong>: Specific files examined, modified, or created — with code snippets</li>
<li><strong>Errors and Fixes</strong>: All errors encountered and how they were fixed</li>
<li><strong>Problem Solving</strong>: Resolved issues and ongoing troubleshooting</li>
<li><strong>All User Messages</strong>: Non-tool user messages for understanding intent changes</li>
<li><strong>Pending Tasks</strong>: Outstanding tasks explicitly requested</li>
<li><strong>Current Work</strong>: Specific work in progress before the summary request</li>
<li><strong>Optional Next Steps</strong>: Next steps related to recent work</li>
</ol>
<p>The prompt uses XML format (Claude models are trained extensively on XML tags) and an <code>&lt;analysis&gt;</code> block for structured thinking before the final summary.</p>
<p><strong>Why these 8 directions?</strong></p>
<ol>
<li><strong>Technical Context</strong>: Rebuilding the development environment</li>
<li><strong>Project Overview</strong>: Understanding global architecture</li>
<li><strong>Code Changes</strong>: Recording specific work outputs</li>
<li><strong>Debugging &amp; Issues</strong>: Avoiding repeating mistakes</li>
<li><strong>Current Status</strong>: Tracking task progress</li>
<li><strong>Pending Tasks</strong>: Maintaining task continuity</li>
<li><strong>User Preferences</strong>: Working memory about the project</li>
<li><strong>Key Decisions</strong>: Preserving decision history</li>
</ol>
<p>After LLM generates the summary, add an <strong>opening statement</strong>: "Context has been compressed using structured 8-section algorithm. All essential information has been preserved for seamless continuation."</p>
<h2>2. LLM Compression — Gemini's Prompt</h2>
<p>Gemini-cli also uses LLM summarization but differs in key information retention and invocation:</p>
<ol>
<li>Only 5 key information categories</li>
<li>Uses "scratchpad" chain-of-thought to enhance extraction</li>
</ol>
<p>Gemini's prompt instructs the model to first think in a private <code>&lt;scratchpad&gt;</code>, then generate a <code>&lt;state_snapshot&gt;</code> XML with:</p>
<ol>
<li><strong>Overall Goal</strong>: User's high-level objective</li>
<li><strong>Key Knowledge</strong>: Critical facts, conventions, and constraints</li>
<li><strong>File System State</strong>: Files created, read, modified, or deleted</li>
<li><strong>Recent Actions</strong>: Summary of recent agent operations and results</li>
<li><strong>Current Plan</strong>: Step-by-step plan with completion markers</li>
</ol>
<h2>3. Context Compression — Tool Message Trimming</h2>
<p>Instead of LLM-based compression, this strategy cleans tool inputs and outputs directly:</p>
<blockquote>
<p>Context editing automatically clears stale tool calls and results from within the context window when approaching token limits, effectively extending how long agents can run without manual intervention.</p>
</blockquote>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-49.BD1QfVdM_ke5z.webp" alt="Token Distribution of Tool Calls in Context" /></p>
<p>In most Agent interactions, tool outputs (especially read tools) consume the most context. User inputs and model outputs are relatively small. Prioritizing tool-related context removal is reasonable.</p>
<p>Implementation approach:</p>
<ul>
<li>Filter tool inputs and outputs from history</li>
<li>Decide whether to remove all or keep the last N tool call rounds</li>
<li>Produce optimized context</li>
</ul>
<p>The code identifies "tool rounds" (assistant message with tool_calls + corresponding tool result messages), keeps the most recent N rounds, and removes the rest while preserving all non-tool messages.</p>
<p>Following Cursor's approach: when providing summaries, also provide a history file location so the Agent can search for details not included in the summary.</p>
<h2>4. Context Compression — Middle vs Oldest Strategy Selection</h2>
<p>An elegant compression approach that uses algorithmic judgment rather than LLM compression — more controllable but more complex to develop.</p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-50.CjgfkBoD_1V3wTl.webp" alt="Middle and Oldest Removal Strategies" /></p>
<p>Three removal strategies:</p>
<ol>
<li><strong>Middle removal</strong>: Keep beginning and end, remove middle messages</li>
<li><strong>Oldest removal</strong>: Prioritize removing oldest messages, keep newer ones</li>
<li><strong>Hybrid</strong>: Intelligently combine both strategies</li>
</ol>
<h3>4.1 Strategy Selection Method</h3>
<p>Three-layer selection:</p>
<ol>
<li>First layer: Based on provider/model</li>
<li>Second layer: Based on conversation characteristics</li>
<li>Third layer: Confidence judgment</li>
</ol>
<h3>4.2 Provider/Model-Based Selection</h3>
<table>
<thead>
<tr>
<th>Provider</th>
<th>Model</th>
<th>Strategy</th>
<th>Reason</th>
</tr>
</thead>
<tbody>
<tr>
<td>OpenAI</td>
<td>GPT-4</td>
<td>Hybrid</td>
<td>Balanced start/end retention</td>
</tr>
<tr>
<td>OpenAI</td>
<td>O1</td>
<td>Middle removal</td>
<td>Higher retention for context-hungry models</td>
</tr>
<tr>
<td>Anthropic</td>
<td>All</td>
<td>Oldest removal</td>
<td>More end-message retention</td>
</tr>
<tr>
<td>Google</td>
<td>1.5</td>
<td>Middle removal</td>
<td>Large context, conservative compression</td>
</tr>
<tr>
<td>LMStudio/Ollama</td>
<td>All</td>
<td>Hybrid</td>
<td>Small context, aggressive compression</td>
</tr>
</tbody>
</table>
<h3>4.3 Conversation Characteristics-Based Selection</h3>
<p>Only triggered when the first step outputs "hybrid." Analyzes: total messages, average message length, compression ratio, recent message token ratio, presence of long/system/tool messages, and compression severity (light &gt;80%, moderate &gt;60%, heavy ≤60%).</p>
<p><strong>Rules:</strong></p>
<ol>
<li>Light compression + short conversation → Middle removal (confidence: 0.8)</li>
<li>Heavy compression + long conversation → Oldest removal (confidence: 0.9)</li>
<li>High recent message ratio → Middle removal (confidence: 0.7)</li>
<li>Long messages + significant compression → Oldest removal (confidence: 0.6)</li>
<li>Tool or system messages present → Middle removal (confidence: 0.7)</li>
</ol>
<h3>4.4 Adaptive Strategy Selection</h3>
<p>When confidence drops below 0.6, the system runs both strategies and calculates efficiency scores:</p>
<p><strong>Efficiency = Token reduction (60% weight) + Message preservation (40% weight)</strong></p>
<p>Example: 15 messages, 9000 tokens, target 6000:</p>
<ul>
<li>Middle removal: 6200 tokens, 12 messages kept → efficiency 0.5066</li>
<li>Oldest removal: 5800 tokens, 10 messages kept → efficiency 0.4804</li>
</ul>
<p>Middle removal wins despite less token reduction, because it preserves more messages. The system balances both objectives to select the optimal strategy.</p>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-03T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Agent Evaluation: Methods and Frameworks]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/agent-eval-overview/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/agent-eval-overview/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Why Agent evaluation matters so much — the four components, complete workflow, and three scoring methods (code-based, human, model-based) explained in practice.]]></summary>
        <content type="html"><![CDATA[<h2>Preface</h2>
<ul>
<li>Claude Cookbooks: https://github.com/anthropics/claude-cookbooks</li>
<li>LangFuse documentation: https://langfuse.com/docs/evaluation/overview</li>
<li>promptfoo framework: https://github.com/promptfoo/promptfoo</li>
</ul>
<h2>1. Why Agent Evaluation Matters</h2>
<p>LLM output has uncontrollable factors. For production-grade LLM applications, stability is paramount. Mature evaluation frameworks not only make applications more stable but also reveal model potential and boundaries for better iteration.</p>
<p>Key quotes:</p>
<blockquote>
<ol>
<li>Teams' inability to effectively evaluate model performance is the biggest barrier to LLM production use cases, turning prompt design into art rather than science.</li>
<li>Although evaluation takes significant time, doing it upfront saves developers time long-term and enables better products to ship faster.</li>
</ol>
</blockquote>
<p>Evaluation benefits for LLM application development — quantifying model boundary capabilities:</p>
<ol>
<li><strong>Iterative prompt optimization</strong>: Is our V2 prompt better than V1?</li>
<li><strong>Pre/post-deployment quality assurance</strong>: Did our latest prompt update cause performance degradation?</li>
<li><strong>Objective model comparison</strong>: When switching to a more advanced model, can we maintain or improve evaluation performance?</li>
<li><strong>Potential cost savings</strong>: When switching to a faster, cheaper model, can we maintain evaluation performance?</li>
</ol>
<h2>2. Evaluation Components</h2>
<p>A well-designed evaluation framework has four main components:</p>
<ol>
<li><strong>Example inputs</strong>: Instructions or questions for the model — key is designing inputs that accurately represent real-world usage scenarios</li>
<li><strong>Gold standard answers</strong>: Correct or ideal responses as baselines — creating high-quality standards often requires domain expert involvement</li>
<li><strong>Model output</strong>: What the LLM actually generates based on example inputs</li>
<li><strong>Score</strong>: A quantitative or qualitative value representing model performance on that specific input</li>
</ol>
<p><strong>At least 100+ sets of example inputs and gold standard answers</strong> are needed for meaningful evaluation.</p>
<h2>3. Evaluation Workflow</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-46.C_qF9L34_Z17JCOO.webp" alt="Agent evaluation workflow" /></p>
<p>Step-by-step:</p>
<ol>
<li>Prepare test cases (example inputs + gold standard answers)</li>
<li>Split into two batches: 80% development set, 20% holdout set</li>
<li>Design first-version prompt based on intuition</li>
<li>Test on development set</li>
<li>If results are poor, optimize prompt based on test results — iterate until satisfactory</li>
<li>Test against the holdout set to verify generalization</li>
<li>If the <strong>gap between holdout and development results</strong> is within ~10%, it passes</li>
<li>If the gap exceeds 10%, the prompt is overfitting to the development set — return to prompt optimization</li>
</ol>
<p>Two additional evaluation factors beyond accuracy:</p>
<ul>
<li><strong>Edge case coverage</strong>: Model performance on extreme inputs</li>
<li><strong>Performance testing</strong>: Model response time</li>
</ul>
<p>The two most important aspects:</p>
<ol>
<li><strong>Writing evaluation questions and gold standards</strong>: Time-consuming but one-time cost, reusable</li>
<li><strong>Ongoing scoring costs</strong>: Frequent evaluation runs incur model costs if using LLM scoring — build fast and economical evaluation systems</li>
</ol>
<h2>4. Evaluation Methods</h2>
<p>Three common methods:</p>
<ul>
<li>Code-based scoring: Standard code to match and judge model output</li>
<li>Human scoring: Manual review and scoring</li>
<li>Model-based scoring: Another LLM evaluates the output</li>
</ul>
<p>Prioritize model and code-based scoring over human scoring, which is more expensive and slower.</p>
<h3>4.1 Code-Based Scoring</h3>
<p><strong>Characteristics</strong>: Programmatic approach for tasks with clear, objective criteria.</p>
<p><strong>Advantages</strong>: Speed and scalability — can consistently process thousands of evaluations. Limited ability to handle nuance or subjectivity.</p>
<p><strong>Forms</strong>:</p>
<ol>
<li>Exact string matching: Output must exactly match gold standard</li>
<li>Keyword presence checking: Whether output contains certain key words/phrases</li>
<li>Regular expressions: Check complex text patterns</li>
</ol>
<h4>Example</h4>
<p>Using the relatively weak <code>Qwen2-7B-Instruct</code> model to demonstrate the full evaluation flow with a sentiment analysis task:</p>
<p>Step 1 — Prepare evaluation dataset:</p>
<pre><code>let testCases = [
  { id: 1, text: 'Amazing! Very satisfied, five stars!', expected: 'positive', reason: 'Clear positive words' },
  { id: 2, text: 'Fast shipping, quality exceeds expectations', expected: 'positive', reason: 'Multiple positive descriptions' },
  { id: 3, text: 'Garbage product, completely unusable, got refund', expected: 'negative', reason: 'Clear negative words' },
  // ... more test cases
];
</code></pre>
<p>Step 2 — First-version prompt:</p>
<pre><code>let promptV1 = (text: string) =&gt; `
Determine the sentiment of the following text, answer "positive", "negative", or "neutral".
Text: ${text}
Answer with one word only.
`;
</code></pre>
<p>Step 3 — Run and score: Accuracy 83.33% (2 failures)</p>
<p>Step 4 — Optimize prompt with rules for sarcasm detection and transition sentence handling</p>
<p>Step 5 — Run optimized prompt: Accuracy 100%</p>
<p>Step 6 — Proceed to holdout set testing or pass evaluation</p>
<h3>4.2 Human-Based Scoring</h3>
<p><strong>Characteristics</strong>: Gold standard for tasks requiring nuanced understanding or subjective judgment.</p>
<p><strong>Advantages</strong>: Excels at evaluating tone, creativity, complex reasoning, and factuality. <strong>Disadvantages</strong>: Time-consuming, potentially expensive at scale, and susceptible to inter-rater inconsistency.</p>
<p><strong>Forms</strong>:</p>
<ol>
<li>Expert review: Domain experts evaluate accuracy and depth</li>
<li>User experience panels: Groups evaluate clarity, helpfulness, and engagement</li>
</ol>
<h3>4.3 Model-Based Scoring</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/image-47.D3AfmE8r_Z1agN29.webp" alt="Model-based scoring" /></p>
<p><strong>Characteristics</strong>: Falls between code-based and human-based methods, using another LLM to evaluate output.</p>
<p><strong>Advantages</strong>: Handles more complex and subjective evaluations than code-based scoring while being faster and more scalable than human scoring. Requires strong prompt engineering for reliable results, with risk of the scoring LLM introducing its own biases.</p>
<h4>Writing Evaluation Model Prompts</h4>
<p>Core elements:</p>
<ul>
<li>Original prompt or question</li>
<li>Model output to evaluate</li>
<li>Evaluation criteria or guidelines</li>
<li>Instructions for how to evaluate and score</li>
</ul>
<p>Common evaluation criteria:</p>
<ol>
<li>How apologetic is this response?</li>
<li>Is the response factually accurate given the context?</li>
<li>Does the response excessively reference its own context?</li>
<li>Does it truly answer the question appropriately?</li>
<li>How well does it align with our tone/brand/style guidelines?</li>
</ol>
<h4>Evaluation Model Positioning</h4>
<p>A qualified evaluation model must maintain objectivity. Most models default to being friendly with apologetic tendencies.</p>
<p>Add perspective constraints to the evaluation prompt: <strong>"Do not apologize or use apologetic language. Be objective and neutral."</strong></p>
<h4>Evaluation Example</h4>
<p>Step 1 — User input: "Write a slogan for a children's toy store"</p>
<p>Step 2 — Tested model output: "Our store offers high-quality toys, welcome to purchase."</p>
<p>Step 3 — Evaluation LLM scores against criteria: child-friendly, lively tone, total score 10</p>
<p>Step 4 — Result: 4/10. Reason: Tone is too formal and serious, doesn't match the lively positioning of a children's toy store.</p>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-07-02T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Integrating a Skill System into Your Agent]]></title>
        <id>https://wakeup-jin-blog.netlify.app/en/posts/agent-skill-integration/</id>
        <link href="https://wakeup-jin-blog.netlify.app/en/posts/agent-skill-integration/"/>
        <updated>2026-07-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Core steps for adding Skill support to your Agent — discovery, parsing, usage, management, and the practice of progressive disclosure strategy.]]></summary>
        <content type="html"><![CDATA[<p>When adding Skill support to your own Agent, the core development steps are: <strong>Discovery, Parsing, Usage, Management</strong>.</p>
<ol>
<li>Discovery: Where are your Skills stored — local or cloud? What's the priority between project-level and user-level? How do you determine that a folder is a Skill?</li>
<li>Parsing: Extract the metadata from SKILL.md</li>
<li>Usage: How does the Agent use the parsed metadata — system prompt or tool description? The subsequent progressive disclosure strategy — use a read tool or an internal activation tool?</li>
<li>Management: How to maintain the validity of Skills loaded into context? Should Skill content be protected during context compression?</li>
</ol>
<p><strong>The core development principle is also the core feature of Skills: Progressive Disclosure</strong></p>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/BH9kbQf7GoZGUXx5RHDcrzuDnfh.C8QTNaTo_2uvR7x.webp" alt="Progressive Skill loading" /></p>
<ul>
<li>First-level disclosure: At session startup, load <strong>metadata (name + description)</strong> into context</li>
<li>Second-level disclosure: When a Skill is activated — i.e., the Agent matches user input to a Skill's metadata — load the <strong>complete SKILL.md content</strong> into context</li>
<li>Third-level disclosure: After the full SKILL.md content is loaded, if the task complexity is high, the Agent loads more detailed guidance — <strong>scripts, references, and static assets</strong> — on demand</li>
</ul>
<h2>1. Discovery</h2>
<p>The Agent needs to discover which Skills are available in the runtime environment from corresponding file directories. Most Agents run locally, so we'll focus on local Skill discovery.</p>
<p>Skill directory scope is divided into two types: <strong>user global scope and project local scope</strong></p>
<ul>
<li>Project local scope: Skills that only apply to the current project, e.g., frontend design Skill, React best practices Skill</li>
<li>User global scope: Skills that apply to all user projects, e.g., find-skills, pptx (PPT generation Skill)</li>
</ul>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/XF5ybPkrbolYg6xGvAfciXZEnvd.C3ajlNAh_25AgOB.webp" alt="Skill discovery" /></p>
<p>The specific Skill directory paths are:</p>
<ol>
<li><code>&lt;project&gt;/.&lt;agent-client&gt;/skills/</code>: Project-scoped Skills</li>
<li><code>&lt;project&gt;/.agents/skills/</code></li>
<li><code>~/.&lt;agent-client&gt;/skills/</code>: Global-scoped Skills</li>
<li><code>~/.agents/skills/</code></li>
</ol>
<p>You'll notice the <code>/.agents/</code> path exists because it has become a widely adopted convention for sharing skills across different clients. For example:</p>
<blockquote>
<p>Someone might develop a-agent-client with Skills in <code>~/.a-agent-client/skills/</code>. When you develop b-agent-client and want to use a's Skills, you'd need compatibility — reading specific directories like <code>~/.a-agent-client</code>. One is fine, but what about many with different paths? So everyone adopted a convention: regardless of the client, all installed Skills can be provided under <code>~/.agents/skills/</code>, enabling cross-client compatibility.</p>
</blockquote>
<p><strong>Reading from <code>/.agents/</code> means Skills installed by other compliant clients are automatically visible to yours, and vice versa.</strong></p>
<p><strong>When the same Skill appears in both user global and project local scope</strong>, the priority is:</p>
<ul>
<li>Project-level takes priority over user-level</li>
<li>Within the same scope, priority follows discovery order</li>
</ul>
<p>Trust checking is designed because some pulled projects may contain potentially malicious or insecure Skills that could leak secrets.</p>
<p>So in the Agent's configuration file, you can design a Skill trust check layer. Within project scope, only trusted Skills can be loaded — this is determined at the business logic level.</p>
<p>Development tips:</p>
<ul>
<li>Skip directories that don't contain Skills, e.g., node_modules/</li>
<li>Consider respecting the project's .gitignore file, avoiding scanning build artifacts like dist/</li>
<li>Don't recursively search endlessly — set a maximum depth (5-6 levels) and maximum file count</li>
</ul>
<h2>2. Parsing</h2>
<p>At the Agent session start phase, Skill metadata needs to be loaded into context. So after getting the Skill file paths, the next step is parsing SKILL.md metadata.</p>
<p><strong>A SKILL.md file contains two parts:</strong></p>
<ol>
<li>YAML front matter separated by <code>---</code> delimiters</li>
<li>MD-formatted content after the closing delimiter</li>
</ol>
<p>The metadata fields and constraints are:</p>
<ul>
<li>name (required): Skill name, max 64 characters, lowercase letters, numbers, and hyphens only</li>
<li>description (required): Skill description, max 1024 characters</li>
<li>license (optional): License name or file reference</li>
<li>compatibility (optional): Environment requirements</li>
<li>metadata (optional): Additional metadata</li>
<li>allowed-tools (optional): List of tools the Skill is allowed to execute</li>
</ul>
<p>Detailed development steps:</p>
<ol>
<li>Find the start and end delimiters in the SKILL.md file</li>
<li>Parse the YAML block, extracting name, description, and other optional fields</li>
<li>The MD content after the closing delimiter is the SKILL.md body</li>
</ol>
<p><strong>When parsing YAML, don't be too strict with error handling — minor errors shouldn't prevent Skill parsing. Return error info as warnings to the user.</strong></p>
<p>The parsed metadata needs to be loaded into the Agent's context. We can use a Map format, <strong>storing metadata in memory</strong> with name as key. The value needs at least three fields:</p>
<ul>
<li>name</li>
<li>description</li>
<li><strong>location: absolute path to the SKILL.md file</strong></li>
</ul>
<h2>3. Usage</h2>
<h3>3.1 Placing Metadata in System Prompt</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/OtzQbJZakoj0TNxJrWAcdLKFnbb.CAEBZtHQ_Z1Ois7i.webp" alt="Skill metadata in the system prompt" /></p>
<ol>
<li>At session start, place metadata in the system prompt <strong>with a brief Skill usage instruction telling the model how and when to use it</strong> — first-level disclosure</li>
<li>When user input triggers a matching Skill, the Agent calls a read tool to load the complete SKILL.md — second-level disclosure</li>
<li>After the full SKILL.md is loaded, if the Agent needs more detailed guidance, it reads references, assets, and scripts from paths in the SKILL.md — third-level disclosure</li>
<li>If scripts need execution, the Agent calls the Bash tool</li>
</ol>
<p>Use structured formats (XML, JSON, etc.) when placing metadata in the system prompt — this is very effective for context management.</p>
<pre><code>&lt;available_skills&gt;
  &lt;skill&gt;
    &lt;name&gt;code-review&lt;/name&gt;
    &lt;description&gt;Review code for bugs, style issues, and best practices. Use when the user wants feedback on their code.&lt;/description&gt;
    &lt;location&gt;/home/user/.agents/skills/code-review/SKILL.md&lt;/location&gt;
  &lt;/skill&gt;
&lt;/available_skills&gt;
</code></pre>
<p>The location field serves two purposes:</p>
<ol>
<li>Provide the correct path parameter for the read tool</li>
<li>Give the model a base path reference for correctly reading referenced resources</li>
</ol>
<h3>3.2 Placing Metadata in a Dedicated Tool</h3>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/UhRmbzL4moEjr6xkx64cYcnOn9d.BBTH1WJp_Z1vIv1.webp" alt="Skill metadata exposed through a dedicated tool" /></p>
<ol>
<li>At session start, Skill metadata is provided in tool description format — first-level disclosure</li>
<li>When the Agent needs complete SKILL.md content, it passes the name as a parameter and the tool returns the content — second-level disclosure</li>
<li>In third-level disclosure, the Agent uses read tools to get full reference resource content</li>
<li>The Bash tool can execute Skill scripts</li>
</ol>
<p>Using dedicated tools vs system prompts — dedicated tools have advantages in <strong>development control</strong>:</p>
<ul>
<li>Control returned content — only return body content, not duplicate metadata</li>
<li>During context management, tool results can be specially marked to skip compression</li>
<li>Reference resources are presented in structured list format, more model-friendly</li>
<li>Enable unique control flows</li>
<li>Enable statistics and analytics</li>
</ul>
<pre><code>&lt;skill_content name="code-review"&gt;
# Code Review

## When to Use
Use this skill when users need code review, including bug detection,
code style checking, and best practice suggestions.

## Review Steps
1. Read the code and understand its intent
2. Check style issues against references/style-guide.md
3. Run scripts/lint-check.sh for static analysis
4. Output a structured review report

Skill directory: /home/user/.agents/skills/code-review

&lt;skill_resources&gt;
  &lt;file&gt;scripts/lint-check.sh&lt;/file&gt;
  &lt;file&gt;references/style-guide.md&lt;/file&gt;
  &lt;file&gt;references/common-bugs.md&lt;/file&gt;
&lt;/skill_resources&gt;
&lt;/skill_content&gt;
</code></pre>
<p>For <code>skill_resources</code>, instead of relying on SKILL.md to describe references, as a tool result we can read all reference, scripts, and asset folders under the skill, then include file paths in the <code>skill_resources</code> tag. <strong>Limit the file list size and signal to the model that "the current list may be incomplete" so the model isn't constrained during autonomous execution.</strong></p>
<h2>4. Management</h2>
<p><img src="https://wakeup-jin-blog.netlify.app/_astro/Kjujba3FOodXLnxZG4lcnF3YnUh.C8qourqO_2oQIMc.webp" alt="Skill management" /></p>
<p>The purpose of progressive loading is to <strong>avoid preloading all Skills</strong>, since some might not be used initially — loading them would waste context.</p>
<p><strong>However, already-loaded Skill content is worth keeping throughout the session</strong>, since the Skill has become behavioral guidance for the Agent. Blindly compressing it would degrade performance. Two approaches to retain Skill content:</p>
<ol>
<li>System prompt approach: Identify structured tags in read tool results to preserve Skill content</li>
<li>Dedicated tool approach: Mark skill activation tool output as protected, checking the mark during compression</li>
</ol>
<p>This depends on the situation — if conversations are long with many Skills and a small context window, compression is the better choice.</p>
<p><strong>After compression, explicitly prompt the model: "Skills were also compressed — reload them if needed."</strong> Otherwise the model may fall into compression hallucination, believing it still has the Skill loaded.</p>
<p>A more advanced approach: <strong>running Skills with a subAgent</strong></p>
<p>The subAgent's entire execution (Skill instructions + reference files + intermediate reasoning) happens in its own context window, leaving the main Agent's context completely unpolluted.</p>
<p>Whether to use a subAgent for Skill execution should be the main Agent's decision, e.g., automatically delegating when task complexity exceeds a threshold.</p>
<h2>5. Quick Build</h2>
<p>The above describes building Skill support from scratch. The current ecosystem is mature — many Agent SDKs support Skills out of the box.</p>
<p>Using Claude Agent SDK as an example:</p>
<ol>
<li>Agent runtime file:</li>
</ol>
<pre><code>"""Simplified version showing core flow steps"""
async def _run_repl_async() -&gt; None:
    config = load_runtime_config()
    apply_runtime_env(config)
    client = build_client(config)

    try:
        user_input = input("\n&gt; ").strip()
    except (EOFError, KeyboardInterrupt):
        return print("\nGoodbye!")

    try:
        print("[Sending request...]")
        await client.query(user_input)
        print("[Receiving response...]")
        events = [e async for e in _iter_events(client)]
    except Exception as exc:
        print(f"[Error] {exc}")
</code></pre>
<ol>
<li>Core SDK configuration:</li>
</ol>
<pre><code>"""SDK wrapper - simplified"""
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions

ALLOWED_TOOLS = ["Skill", "Read", "Write", "Edit", "Bash", "Grep", "Glob"]

def build_client(config):
    options = ClaudeAgentOptions(
        setting_sources=["project", "user"],
        allowed_tools=ALLOWED_TOOLS,
        model="deepseek-chat",
        env={
            "ANTHROPIC_AUTH_TOKEN": config.api_key,
            "ANTHROPIC_BASE_URL": config.base_url,
        },
        add_dirs=["/xxx/xxxx/.agents/skills"]
    )
    return ClaudeSDKClient(options=options)
</code></pre>
<p>Similar SDKs include pi-mono's pi-coding-agent core package and kimi Agent SDK.</p>
<p><strong>If speed is the priority, using mature Agent SDKs for Skill support is perfectly viable. Your overall Agent design then needs to align with these SDKs — there are pros and cons that developers should weigh based on their scenarios.</strong></p>
<ul>
<li>Building from scratch: higher freedom, more customizable</li>
<li>Using SDKs: faster speed, easier iteration, lower development difficulty</li>
</ul>
]]></content>
        <author>
            <name>WakeUp-Jin</name>
            <uri>https://wakeup-jin-blog.netlify.app/</uri>
        </author>
        <published>2026-04-14T00:00:00.000Z</published>
    </entry>
</feed>