s08
Фоновые задачи
ПараллелизмBackground Threads + Notifications
198 LOC6 инструментовBackgroundManager + notification queue
Run slow operations in the background; the agent keeps thinking ahead
s01 > s02 > s03 > s04 > s05 > s06 | s07 > [ s08 ] s09 > s10 > s11 > s12
"Запускайте медленные операции в фоне; агент продолжает думать" -- демон-потоки выполняют команды, внедряют уведомления по завершении.
Проблема
Некоторые команды занимают минуты: 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 --+
Как Это Работает
- BackgroundManager отслеживает задачи с потокобезопасной очередью уведомлений.
class BackgroundManager:
def __init__(self):
self.tasks = {}
self._notification_queue = []
self._lock = threading.Lock()
run()запускает демон-поток и возвращается сразу.
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"
- Когда подпроцесс завершается, его результат попадает в очередь уведомлений.
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]})
- Цикл агента освобождает очередь уведомлений перед каждым вызовом LLM.
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"<background-results>\n{notif_text}\n"
f"</background-results>"})
messages.append({"role": "assistant",
"content": "Noted background results."})
response = client.messages.create(...)
Цикл остаётся однопоточным. Только ввод/вывод подпроцессов параллелизуется.
Что Изменилось с s07
| Компонент | До (s07) | После (s08) |
|---|---|---|
| Инструменты | 8 | 6 (base + background_run + check) |
| Выполнение | Только блокирующее | Блокирующее + фоновые потоки |
| Уведомление | Нет | Очередь освобождаемая за цикл |
| Параллелизм | Нет | Демон-потоки |
Попробуйте
python agents/s08_background_tasks.py
Запустите "sleep 5 && echo done" в фоне, затем создайте файл, пока оно выполняетсяЗапустите 3 фоновые задачи: "sleep 2", "sleep 4", "sleep 6". Проверьте их статус.Запустите pytest в фоне и продолжайте работать над другими задачами
