# s08: Background Tasks (后台任务) `s01 > s02 > s03 > s04 > s05 > s06 | s07 > [ s08 ] s09 > s10 > s11 > s12` > *"慢操作丢后台, agent 继续想下一步"* -- 后台线程跑命令, 完成后注入通知。 > > **Harness 层**: 后台执行 -- 模型继续思考, harness 负责等待。 ## 问题 有些命令要跑好几分钟: `npm install`、`pytest`、`docker build`。阻塞式循环下模型只能干等。用户说 "装依赖, 顺便建个配置文件", 智能体却只能一个一个来。 ## 解决方案 ``` Main thread Background thread +-----------------+ +-----------------+ | agent loop | | subprocess runs | | ... | | ... | | [LLM call] <---+------- | enqueue(result) | | ^drain queue | +-----------------+ +-----------------+ Timeline: Agent --[spawn A]--[spawn B]--[other work]---- | | v v [A runs] [B runs] (parallel) | | +-- results injected before next LLM call --+ ``` ## 工作原理 1. BackgroundManager 用线程安全的通知队列追踪任务。 ```python class BackgroundManager: def __init__(self): self.tasks = {} self._notification_queue = [] self._lock = threading.Lock() ``` 2. `run()` 启动守护线程, 立即返回。 ```python def run(self, command: str) -> str: task_id = str(uuid.uuid4())[:8] self.tasks[task_id] = {"status": "running", "command": command} thread = threading.Thread( target=self._execute, args=(task_id, command), daemon=True) thread.start() return f"Background task {task_id} started" ``` 3. 子进程完成后, 结果进入通知队列。 ```python def _execute(self, task_id, command): try: r = subprocess.run(command, shell=True, cwd=WORKDIR, capture_output=True, text=True, timeout=300) output = (r.stdout + r.stderr).strip()[:50000] except subprocess.TimeoutExpired: output = "Error: Timeout (300s)" with self._lock: self._notification_queue.append({ "task_id": task_id, "result": output[:500]}) ``` 4. 每次 LLM 调用前排空通知队列。 ```python def agent_loop(messages: list): while True: notifs = BG.drain_notifications() if notifs: notif_text = "\n".join( f"[bg:{n['task_id']}] {n['result']}" for n in notifs) messages.append({"role": "user", "content": f"\n{notif_text}\n" f""}) messages.append({"role": "assistant", "content": "Noted background results."}) response = client.messages.create(...) ``` 循环保持单线程。只有子进程 I/O 被并行化。 ## 相对 s07 的变更 | 组件 | 之前 (s07) | 之后 (s08) | |----------------|------------------|------------------------------------| | Tools | 8 | 6 (基础 + background_run + check) | | 执行方式 | 仅阻塞 | 阻塞 + 后台线程 | | 通知机制 | 无 | 每轮排空的队列 | | 并发 | 无 | 守护线程 | ## 试一试 ```sh cd learn-claude-code python agents/s08_background_tasks.py ``` 试试这些 prompt (英文 prompt 对 LLM 效果更好, 也可以用中文): 1. `Run "sleep 5 && echo done" in the background, then create a file while it runs` 2. `Start 3 background tasks: "sleep 2", "sleep 4", "sleep 6". Check their status.` 3. `Run pytest in the background and keep working on other things`