Sub-agents

Sub-agents là các agent chạy nền được tạo ra từ một agent đang chạy. Chúng chạy trong Session riêng (agent:<agentId>:subagent:<uuid>) và khi hoàn thành, sẽ thông báo kết quả về Channel chat gốc.

Lệnh Slash

Dùng /subagents để kiểm tra hoặc điều khiển các sub-agent đang chạy cho Session hiện tại:

  • /subagents list
  • /subagents stop <id|#|all>
  • /subagents log <id|#> [limit] [tools]
  • /subagents info <id|#>
  • /subagents send <id|#> <message>

/subagents info hiển thị metadata của lần chạy (trạng thái, timestamps, session id, đường dẫn transcript, cleanup).

Mục tiêu chính:

  • Song song hóa các công việc “nghiên cứu / tác vụ dài / tool chậm” mà không chặn agent chính.
  • Giữ sub-agents cô lập theo mặc định (tách Session + sandboxing tùy chọn).
  • Giữ tool khó bị lạm dụng: sub-agents không có session tools theo mặc định.
  • Tránh phân nhánh lồng nhau: sub-agents không thể tạo sub-agents.

Lưu ý về chi phí: mỗi sub-agent có Context riêng và sử dụng Token riêng. Với các tác vụ nặng hoặc lặp lại, các bạn nên đặt model rẻ hơn cho sub-agents và giữ agent chính dùng model chất lượng cao hơn. Các bạn có thể cấu hình qua agents.defaults.subagents.model hoặc override theo từng agent.

Tool

Dùng sessions_spawn:

  • Khởi động một sub-agent (deliver: false, global lane: subagent)
  • Sau đó chạy bước announce và đăng reply announce lên Channel chat gốc
  • Model mặc định: kế thừa từ caller trừ khi các bạn đặt agents.defaults.subagents.model (hoặc theo agent agents.list[].subagents.model); sessions_spawn.model tường minh vẫn được ưu tiên.

Tham số tool:

  • task (bắt buộc)
  • label? (tùy chọn)
  • agentId? (tùy chọn; tạo dưới agent id khác nếu được phép)
  • model? (tùy chọn; override model của sub-agent; giá trị không hợp lệ sẽ bị bỏ qua và sub-agent chạy trên model mặc định với cảnh báo trong kết quả tool)
  • thinking? (tùy chọn; override mức thinking cho sub-agent)
  • runTimeoutSeconds? (mặc định 0; khi đặt, sub-agent sẽ bị hủy sau N giây)
  • cleanup? (delete|keep, mặc định keep)

Allowlist:

  • agents.list[].subagents.allowAgents: danh sách các agent id có thể được chỉ định qua agentId (["*"] để cho phép bất kỳ). Mặc định: chỉ agent gốc.

Discovery:

  • Dùng agents_list để xem các agent id hiện được phép cho sessions_spawn.

Auto-archive:

  • Các Session sub-agent tự động được archive sau agents.defaults.subagents.archiveAfterMinutes (mặc định: 60).
  • Archive dùng sessions.delete và đổi tên transcript thành *.deleted.<timestamp> (cùng thư mục).
  • cleanup: "delete" archive ngay sau announce (vẫn giữ transcript qua đổi tên).
  • Auto-archive là best-effort; các timer đang chờ sẽ mất nếu Gateway khởi động lại.
  • runTimeoutSeconds không tự động archive; nó chỉ dừng lần chạy. Session vẫn còn cho đến khi auto-archive.

Authentication

Xác thực sub-agent được xử lý theo agent id, không phải theo loại Session:

  • Session key của sub-agent là agent:<agentId>:subagent:<uuid>.
  • Auth store được load từ agentDir của agent đó.
  • Các auth profiles của agent chính được merge vào như fallback; agent profiles sẽ override main profiles khi xung đột.

Lưu ý: việc merge là cộng dồn, nên main profiles luôn có sẵn làm fallback. Xác thực hoàn toàn cô lập theo agent chưa được hỗ trợ.

Announce

Sub-agents báo cáo lại qua bước announce:

  • Bước announce chạy bên trong Session sub-agent (không phải Session gốc).
  • Nếu sub-agent reply chính xác ANNOUNCE_SKIP, không có gì được đăng.
  • Nếu không, reply announce được đăng lên Channel chat gốc qua lệnh gọi agent tiếp theo (deliver=true).
  • Các reply announce giữ nguyên thread/topic routing khi có sẵn (Slack threads, Telegram topics, Matrix threads).
  • Các thông báo announce được chuẩn hóa theo template ổn định:
    • Status: lấy từ kết quả chạy (success, error, timeout, hoặc unknown).
    • Result: nội dung tóm tắt từ bước announce (hoặc (not available) nếu thiếu).
    • Notes: chi tiết lỗi và các thông tin hữu ích khác.
  • Status không được suy ra từ output của model; nó đến từ các tín hiệu kết quả runtime.

Các payload announce bao gồm dòng thống kê ở cuối (ngay cả khi được wrap):

  • Runtime (ví dụ: runtime 5m12s)
  • Sử dụng Token (input/output/total)
  • Chi phí ước tính khi cấu hình giá model (models.providers.*.models[].cost)
  • sessionKey, sessionId, và đường dẫn transcript (để agent chính có thể fetch lịch sử qua sessions_history hoặc kiểm tra file trên đĩa)

Tool Policy (sub-agent tools)

Theo mặc định, sub-agents nhận tất cả tools trừ session tools:

  • sessions_list
  • sessions_history
  • sessions_send
  • sessions_spawn

Override qua config:

{
  agents: {
    defaults: {
      subagents: {
        maxConcurrent: 1,
      },
    },
  },
  tools: {
    subagents: {
      tools: {
        // deny wins
        deny: ["gateway", "cron"],
        // if allow is set, it becomes allow-only (deny still wins)
        // allow: ["read", "exec", "process"]
      },
    },
  },
}

Concurrency

Sub-agents dùng queue lane in-process riêng:

  • Tên lane: subagent
  • Concurrency: agents.defaults.subagents.maxConcurrent (mặc định 8)

Dừng

  • Gửi /stop trong chat gốc sẽ hủy Session gốc và dừng mọi sub-agent đang chạy được tạo từ nó.

Giới hạn

  • Announce của sub-agent là best-effort. Nếu Gateway khởi động lại, công việc “announce back” đang chờ sẽ bị mất.
  • Sub-agents vẫn dùng chung tài nguyên process Gateway; coi maxConcurrent như van an toàn.
  • sessions_spawn luôn non-blocking: nó trả về { status: "accepted", runId, childSessionKey } ngay lập tức.
  • Context của sub-agent chỉ inject AGENTS.md + TOOLS.md (không có SOUL.md, IDENTITY.md, USER.md, HEARTBEAT.md, hoặc BOOTSTRAP.md).