Harness Academy
Tài liệu gốc 06 9 phútTiếng Việt + English
docs/shell.mdXem bản gốc
Ngôn ngữ bài đọc
Bản dịch tiếng Việt

Bản dịch đầy đủ theo đúng cấu trúc tài liệu; code, liên kết và định danh kỹ thuật được giữ nguyên.

Vỏ

Shell cung cấp cho một agent khả năng chạy các lệnh shell, với sự cho phép/từ chối kiểm soát, lọc môi trường và các quy trình nền được quản lý. Nó lộ ra công cụ thực thi lệnh bắt nguồn từ một thư mục đang làm việc và dọn sạch mọi quá trình nền tự động khi quá trình chạy agent kết thúc.

Nguồn

Mặc dù Pydantic AI Harness có trên các bản phát hành 0.x nhưng API có thể thay đổi giữa các bản phát hành nhỏ; khi đó, cảnh báo ngừng sử dụng và hướng dẫn di chuyển ghi chú phát hành sẽ cho bạn (hoặc người đại diện của bạn) biết chính xác cách nâng cấp. Xem chính sách phiên bản.

vấn đề

Các agent thường xuyên cần chạy một bản dựng, một bộ thử nghiệm, một kẻ nói dối hoặc một bản kiểm tra nhanh grep. Kết nối việc xử lý quy trình con -- đầu ra phát trực tuyến, thời gian chờ, cắt bớt, tiêu diệt các tiến trình chạy trốn và dọn dẹp các công việc nền ở cuối quá trình chạy -- là bản soạn sẵn khó sử dụng mà mọi agent đều phát minh lại.

Shell gộp hệ thống ống nước đó vào một khả năng: danh sách cho phép/từ chối có thể định cấu hình, cắt bớt đầu ra được điều chỉnh để giữ phần đuôi hữu ích, thư mục làm việc dính tùy chọn, kiểm soát môi trường có thể giữ máy chủ bí mật từ các lệnh sinh ra và tự động dọn dẹp các tiến trình nền khi quá trình chạy kết thúc.

Cách sử dụng

xây dựng Shell với một thư mục làm việc và chuyển nó tới một Agent thông qua capabilities tham số:

from pydantic_ai import Agent
from pydantic_ai_harness import Shell

agent = Agent(
    'anthropic:claude-sonnet-4-6',
    capabilities=[Shell(cwd='./workspace', allowed_commands=['ls', 'cat', 'rg'])],
)

result = agent.run_sync('List the Python files and summarize the largest one.')
print(result.output)

Theo mặc định Shell chạy trong thư mục hiện tại với lệnh phá hủy tích hợp danh sách từ chối đang hoạt động -- Shell() một mình cấu hình đang hoạt động (nếu được phép).

Công cụ

Shell đóng góp bốn công cụ cho agent:

Công cụMục đích
run_commandChạy lệnh một cách đồng bộ và trả về nhãn stdout/stderr cộng với mã thoát. Tôn vinh thời gian chờ cho mỗi cuộc gọi hoặc mặc định.
start_commandKhởi chạy lệnh chạy dài (máy chủ, trình theo dõi) ở chế độ nền; trả về một ID.
check_commandBáo cáo trạng thái và đầu ra tích lũy của lệnh nền.
stop_commandChấm dứt lệnh nền và trả về đầu ra cuối cùng của nó.

run_command chấp nhận một tùy chọn timeout_seconds đối số ghi đè default_timeout cho một cuộc gọi duy nhất. check_command và stop_command lấy command_id chuỗi được trả về bởi start_command.

Đầu ra được dán nhãn với [stdout] / [stderr] dấu hiệu và một [exit code: N] dòng trên lối ra khác không. Khi nó vượt quá max_output_chars đuôi được giữ lại (phần đầu bị rơi), do đó có lỗi, dấu vết ngăn xếp và [stderr] phần -- mà tất cả đều ở cuối -- tồn tại khi bị cắt cụt. Trạng thái lệnh nền và thoát siêu dữ liệu theo đầu ra đã ghi để chúng vẫn ở phần đuôi được giữ lại.

Điều khiển lệnh

Hai danh sách loại trừ lẫn nhau quyết định những tệp thực thi nào có thể chạy, cộng với các bộ lọc cho toán tử shell và các lệnh tương tác:

Lĩnh vựcHiệu ứng
allowed_commandsNếu không trống thì chỉ những tệp thực thi này mới có thể chạy (danh sách cho phép).
denied_commandsNhững tệp thực thi này luôn bị từ chối (danh sách từ chối).
denied_operatorsToán tử Shell (ví dụ: >, >>, |) bị từ chối khi có mặt.
allow_interactiveNếu False (mặc định), các lệnh mong đợi TTY (vi, sudo, ssh, ...) bị chặn.

allowed_commands và denied_commands loại trừ lẫn nhau -- đặt một, không phải cả hai. Việc đặt các giá trị không trống cho cả hai sẽ làm tăng ValueError khi bộ công cụ được xây dựng. denied_commands mặc định là danh sách các lệnh phá hoại (rm, rmdir, mkfs, dd, format, shutdown, reboot, halt, poweroff, init); chuyển một danh sách trống để vô hiệu hóa nó. Tên thực thi là chiết xuất với shlex, vì vậy các đối số không bỏ qua việc kiểm tra.

trống rỗng allowed_commands bộ sưu tập không chọn chế độ danh sách cho phép. các được cấu hình denied_commands duy trì hoạt động; khi bị bỏ qua, đây là phần tích hợp sẵn danh sách từ chối. Vượt qua denied_commands=[] để tắt tính năng lọc tên lệnh.

Lệnh bị từ chối xuất hiện trong mô hình dưới dạng ModelRetry, không phải là lỗi cứng: quá trình chạy vẫn tiếp tục và mô hình có thể chọn một lệnh được phép thay thế. cũng vậy mọi lỗi khác mà mô hình có thể xử lý: thư mục đang hoạt động và lệnh trước đó bị xóa hoặc thay thế bằng một tập tin và một lệnh mà hệ điều hành từ chối thực hiện spawn vì nó chứa byte NUL hoặc chứa ký tự của hệ điều hành không thể mã hóa. Thất bại mô hình không thể làm gì khi vẫn hủy bỏ quá trình chạy: một máy chủ không thể phân bổ một quy trình, một đối số hoặc môi trường vượt quá kết hợp của nền tảng giới hạn kích thước và ký tự không hợp lệ trong ứng dụng do ứng dụng cung cấp env.

!!! cảnh báo "Nỗ lực hết mình, không phải ranh giới an ninh" allowed_commands là lan can ngăn ngừa tai nạn chứ không phải là ranh giới an ninh. Quá trình xác thực chỉ kiểm tra token đầu tiên và các lệnh được đưa vào danh sách cho phép, chẳng hạn như python, git, uvvà make có thể sinh ra các quá trình tùy ý. Một mô hình mà muốn làm việc xung quanh danh sách cho phép có thể. Đối với công việc không đáng tin cậy, hãy chạy agent bên trong sự cô lập ở cấp hệ điều hành, chẳng hạn như ModalSandbox hoặc một thùng chứa.

Kiểm soát môi trường

Theo mặc định, lệnh sinh ra sẽ kế thừa môi trường đầy đủ của quy trình agent. trong một hộp cát chứa khóa API LLM, token hoặc các bí mật khác, lệnh cho mô hình viết có thể đọc chúng. Hai trường kiểm soát những gì quy trình con nhìn thấy:

Lĩnh vựcHiệu ứng
envMôi trường rõ ràng thay thế tính kế thừa cho môi trường riêng của quy trình con.
denied_env_patternsMô hình toàn cầu (fnmatch) cho các tên biến bị loại khỏi môi trường cơ sở. Gương denied_commands.

env ngăn chặn các biến kế thừa xuất hiện trong chính tiến trình con môi trường (bạn cung cấp PATH và bất cứ điều gì khác mà lệnh cần). denied_env_patterns là một danh sách từ chối đối với môi trường được kế thừa -- nhẹ hơn đối với cấu hình khi bạn chỉ cần bỏ một vài tên nhạy cảm đã biết. hai soạn thảo: khi cả hai được đặt, các mẫu cũng lọc nội dung rõ ràng env. rời đi cả hai đều không được đặt sẽ giữ nguyên mặc định kế thừa mọi thứ.

import os

from pydantic_ai_harness import LLM_API_KEY_ENV_PATTERNS, Shell

# Strip provider credentials from the inherited environment.
Shell(cwd='./repo', denied_env_patterns=LLM_API_KEY_ENV_PATTERNS)

# Or hand the subprocess a fixed environment, inheriting nothing.
Shell(cwd='./repo', env={'PATH': os.environ['PATH'], 'HOME': os.environ['HOME']})

LLM_API_KEY_ENV_PATTERNS bao gồm các tiền tố nhà cung cấp phổ biến (ANTHROPIC_*, GATEWAY_*, GEMINI_*, GOOGLE_*, OPENAI_*, OPENROUTER_*) cộng PYDANTIC_AI_GATEWAY_API_KEY. Nó chỉ nhắm mục tiêu thông tin xác thực LLM -- nó không che giấu các bí mật máy chủ khác (a LOGFIRE_TOKEN, token GitHub, đám mây thông tin đăng nhập) và tiền tố của nó rất thô, vì vậy GOOGLE_* cũng có dải các loại không có thông tin xác thực như GOOGLE_APPLICATION_CREDENTIALS. Hãy đối xử với nó như một điểm bắt đầu và thêm các mẫu của riêng bạn. Nó không phải là mặc định: tước các biến môi trường sẽ âm thầm phá vỡ các agent dựa vào kế thừa thông tin xác thực, vì vậy nó được chọn tham gia.

env được thực thi khi xuất hiện, không được áp dụng dưới dạng bộ lọc hậu định khi đang chạy quy trình: quy trình con bắt đầu với chính xác môi trường được giải quyết (của bạn env, trừ đi bất cứ thứ gì denied_env_patterns loại bỏ khỏi nó). Không có sự kiểm soát nào một ranh giới an ninh. Một lệnh chạy dưới cùng một danh tính hệ điều hành vẫn có thể đọc môi trường của tiến trình cha thông qua các giao diện hệ thống như Linux Procfs, cũng như các tệp máy chủ khác. Sử dụng cách ly cấp hệ điều hành khi có lệnh không đáng tin cậy. Mặt trái của nó là một mẫu đủ rộng để có thể lột bỏ PATH hoặc HOMEhoặc một env bỏ qua chúng, có thể phá vỡ độ phân giải lệnh. Bên ngoài các lệnh vẫn có thể chạy thông qua mặc định tích hợp của shell PATH trên một số hệ thống, nhưng đừng dựa vào nó -- đặt PATH rõ ràng khi bạn thay thế môi trường.

Quá trình nền

start_command ghi stdout/stderr vào tệp tạm thời và trả về một ID ngắn. sử dụng check_command(command_id) để thăm dò ý kiến và stop_command(command_id) chấm dứt và thu thập đầu ra cuối cùng. Các tiến trình được khởi chạy trong phiên riêng của chúng (start_new_session) để toàn bộ nhóm quy trình có thể được báo hiệu -- SIGTERM, leo thang đến SIGKILL sau một thời gian ân hạn.

Khi kết thúc quá trình dọn dẹp bộ công cụ sẽ chấm dứt mọi nền vẫn đang chạy xử lý và xóa các tập tin tạm thời của nó. runtime agent đi vào bộ công cụ thông qua một AsyncExitStack, do đó quá trình dọn dẹp này sẽ diễn ra cho dù lần chạy thành công hay tăng lên -- một agent quên gọi stop_command sẽ không rò rỉ quá trình.

from pydantic_ai import Agent
from pydantic_ai_harness import Shell

agent = Agent(
    'anthropic:claude-sonnet-4-6',
    capabilities=[Shell(cwd='./app', allowed_commands=['npm', 'curl'])],
)

result = agent.run_sync(
    'Start the dev server with `npm run dev`, wait for it to boot, '
    'then curl http://localhost:3000/health and report the status.'
)
print(result.output)

Thư mục làm việc

Theo mặc định mỗi lệnh chạy trong cwd và cd không có tác dụng lâu dài. Đặt persist_cwd=True làm cd dính trên các cuộc gọi: mỗi lệnh được gói gọn rằng sau khi nó chạy, thư mục làm việc cuối cùng của nó sẽ được ghi vào một thư mục tạm thời riêng tư tập tin và thư mục đó được chuyển vào các cuộc gọi tiếp theo. Con đường chỉ có được cập nhật khi lệnh thoát 0và bản ghi được ghi ngoài dải (không phải thành thiết bị xuất chuẩn) để đầu ra lệnh không bao giờ có thể giả mạo thư mục được theo dõi.

from pydantic_ai import Agent
from pydantic_ai_harness import Shell

agent = Agent(
    'anthropic:claude-sonnet-4-6',
    capabilities=[Shell(cwd='.', persist_cwd=True, allowed_commands=['cd', 'ls', 'pwd'])],
)

Mỗi lần chạy sẽ có một phiên bản bộ công cụ mới, vì vậy thư mục được theo dõi và bất kỳ các tiến trình nền được tách biệt giữa các lần chạy đồng thời và luôn bắt đầu lại tại cấu hình cwd.

Cấu hình

Mỗi lĩnh vực của Shell với mặc định của nó:

from pydantic_ai_harness import Shell

Shell(
    cwd='.',                       # str | Path -- working directory
    allowed_commands=[],           # allowlist (mutually exclusive with denied)
    denied_commands=[...],         # denylist (defaults to destructive commands)
    denied_operators=[],           # blocked shell operators
    default_timeout=30.0,          # seconds, per run_command
    max_output_chars=50_000,       # output cap returned to the model
    persist_cwd=False,             # make cd sticky across calls
    allow_interactive=False,       # allow TTY-style commands
    env=None,                      # explicit env, replacing inheritance (None = inherit)
    denied_env_patterns=[],        # glob patterns stripped from the env
)

Thông số agent (YAML/JSON)

Shell hoạt động với Pydantic AI thông số agent, vì vậy bạn có thể khai báo nó trong một tập tin cấu hình thay vì Python:

# agent.yaml
model: anthropic:claude-sonnet-4-6
capabilities:
  - Shell:
      cwd: ./workspace
      allowed_commands: ['ls', 'cat', 'rg', 'pytest']
from pydantic_ai import Agent
from pydantic_ai_harness import Shell

agent = Agent.from_file('agent.yaml', custom_capability_types=[Shell])

Vượt qua custom_capability_types để trình tải thông số kỹ thuật biết cách khởi tạo Shell.

Đọc thêm

Tham chiếu API

::: pydantic_ai_harness.Shell

Mục lục nguồn