Cửa sổ ngữ cảnh Agent AI: Tối ưu hóa phản hồi API cồng kềnh

Các phản hồi JSON cồng kềnh tiêu tốn cửa sổ ngữ cảnh và ngân sách của tác nhân. Hãy tìm hiểu về việc chọn trường, giới hạn cứng cho danh sách, phép chiếu ở lớp công cụ và tóm tắt phía máy chủ để giữ cho kết quả công cụ nhỏ gọn.

Ashley Innocent

Ashley Innocent

26 tháng 8 2026

Cửa sổ ngữ cảnh Agent AI: Tối ưu hóa phản hồi API cồng kềnh

Apidog cho doanh nghiệp

Triển khai tại chỗ

SSO & RBAC

Tuân thủ SOC 2

Khám phá Apidog Enterprise

Tác nhân yêu cầu hồ sơ khách hàng. API của bạn trả về thông tin khách hàng, cộng với 200 đơn hàng gần nhất của họ, cộng với từng mặt hàng trên các đơn hàng đó, cộng với dấu thời gian ở ba định dạng và một khối _links cho mỗi mục. Bốn mươi nghìn token rơi vào cửa sổ ngữ cảnh. Tác nhân chỉ cần địa chỉ email.

Thực hiện điều đó bốn lần trong một lượt chạy và tác nhân đã tiêu tốn phần lớn ngân sách của mình để đọc dữ liệu JSON mà nó không yêu cầu. Sau đó, những thất bại thú vị bắt đầu: nó quên hướng dẫn ban đầu, nó tóm tắt nhiệm vụ thay vì hoàn thành nó, và chi phí mỗi lượt chạy tăng lên trong khi chất lượng giảm sút.

Đây là vấn đề thiết kế ở tầng API, không phải vấn đề về prompt. Các tác nhân tiêu thụ phản hồi thông qua một cửa sổ cố định, và mỗi trường bạn trả về đều cạnh tranh với các hướng dẫn, cuộc hội thoại và kế hoạch. Hướng dẫn này bao gồm nguồn gốc của sự dư thừa, các mẫu chọn trường và phân trang để khắc phục nó, cách cắt giảm trong lớp công cụ khi bạn không kiểm soát API và cách đo lường sự khác biệt. Bài viết trụ cột của chúng tôi về lý do các tác nhân AI thất bại trong môi trường sản xuất coi việc cạn kiệt ngữ cảnh là một trong những chế độ lỗi cốt lõi, và đây là phần thực hành của vấn đề đó.

Apidog hỗ trợ về mặt đo lường: bạn có thể thấy kích thước phản hồi thực tế cho mỗi endpoint trước khi tác nhân gọi nó, và mô phỏng hình dạng đã được cắt giảm mà bạn muốn trước khi nhóm API triển khai.

Token đi đâu?

Các phản hồi được thiết kế cho trình duyệt và bảng điều khiển mang theo rất nhiều dữ liệu không cần thiết, làm tốn tiền của tác nhân.

Các envelope rườm rà. Một wrapper data, meta, links, included bao quanh một đối tượng năm trường có thể làm tăng gấp đôi dung lượng tải. Các liên kết hypermedia hữu ích cho một client theo dõi chúng. Các tác nhân hầu như không bao giờ làm vậy, và mỗi URL đều là token.

Các khóa lặp lại. JSON lặp lại tên của mỗi trường trên mỗi phần tử mảng. Một danh sách 200 mục với 15 trường mỗi mục phải trả tiền cho 3.000 chuỗi khóa. Đây là lý do tại sao các endpoint danh sách chiếm ưu thế trong việc sử dụng ngữ cảnh.

Mở rộng lồng nhau theo mặc định. Các endpoint nhúng các tài nguyên liên quan thì tiện lợi cho đến khi một tác nhân truy cập chúng. Một khách hàng cộng với các đơn hàng của họ cộng với các mặt hàng là một cây, và cây thì phát triển nhanh chóng.

Các định dạng dư thừa. created_at, created_at_unix, và created_at_human trên cùng một đối tượng có nghĩa là chi phí gấp ba cho một giá trị.

Giá trị null và rỗng. Nhiều trình tuần tự hóa phát ra mọi trường ngay cả khi chưa được đặt. Hai mươi giá trị null trên mỗi bản ghi là hoàn toàn lãng phí.

Một cách hữu ích để hình dung: chi phí token theo dõi kích thước của văn bản đã được tuần tự hóa, không phải số lượng bản ghi. Hai trăm bản ghi với năm trường mỗi bản có thể rẻ hơn một đối tượng lồng nhau sâu.

Quy tắc một: trả về các trường, không phải tài nguyên

Thay đổi có giá trị cao nhất là cho phép người gọi yêu cầu những gì họ cần.

GET /v1/customers/8812?fields=id,email,plan,status
{ "id": "8812", "email": "dana@example.com", "plan": "pro", "status": "active" }

Đó là giảm 90 phần trăm so với một bản ghi đầy đủ trên hầu hết các API, và chỉ mất một buổi chiều để thêm vào. Hướng dẫn thiết kế API của Google ghi lại mẫu field-mask nếu bạn muốn một phiên bản có tiền lệ, và GraphQL giải quyết cùng vấn đề bằng cách buộc phải chọn trường.

Hai lưu ý triển khai. Xác thực danh sách trường với schema và từ chối các tên không xác định, để một trường bị "ảo giác" tạo ra lỗi rõ ràng thay vì một đối tượng bị cắt bớt một cách âm thầm. Và giữ một tập hợp mặc định nhỏ cho những người gọi không gửi gì, thay vì mặc định trả về mọi thứ.

Sau đó, hiển thị tham số cho mô hình trong mô tả công cụ, với các trường được liệt kê rõ ràng:

{
  "name": "getCustomer",
  "description": "Lấy thông tin khách hàng bằng ID. Luôn truyền `fields` với chỉ những gì bạn cần. Các trường có sẵn: id, email, name, plan, status, created_at, billing_address, order_count.",
  "input_schema": {
    "type": "object",
    "required": ["customerId", "fields"],
    "properties": {
      "customerId": { "type": "string" },
      "fields": {
        "type": "array",
        "items": { "type": "string" },
        "description": "Tên các trường cần trả về. Giữ danh sách này ở mức tối thiểu."
      }
    }
  }
}

Các mô tả là nơi duy nhất mô hình học các quy tắc này, và cả hướng dẫn gọi hàm của OpenAI lẫn tài liệu sử dụng công cụ của Anthropic đều nhấn mạnh điều này như nhau. Biến fields thành bắt buộc là một mẹo. Một tham số tùy chọn sẽ bị bỏ qua; một tham số bắt buộc buộc mô hình phải suy nghĩ về những gì nó thực sự cần.

Quy tắc hai: luôn giới hạn danh sách

Các endpoint danh sách không giới hạn là nguồn gốc lớn thứ hai gây ra sự cố. Một tác nhân yêu cầu “các đơn hàng gần đây” và nhận được mọi thứ kể từ năm 2019.

Đặt một giới hạn cứng ở phía máy chủ, không chỉ là giá trị mặc định. Nếu tác nhân gửi limit=5000, hãy trả về 100 và thông báo điều đó. Các hướng dẫn của chúng tôi về phân trang REST APIthiết kế phân trang cho hàng triệu bản ghi đề cập đến cơ chế; các quy tắc dành riêng cho tác nhân thì hẹp hơn:

Cũng cung cấp cho tác nhân một cách để tránh phân trang hoàn toàn. Một endpoint count, một tìm kiếm được lọc với cửa sổ hẹp, hoặc một đối tượng tóm tắt thường sẽ trả lời câu hỏi mà không cần trả về bất kỳ bản ghi nào. Phản hồi rẻ nhất là phản hồi không chứa dữ liệu.

Quy tắc ba: cắt giảm trong lớp công cụ khi API không thuộc sở hữu của bạn

Các API của bên thứ ba sẽ không thêm tính năng chọn trường chỉ vì bạn yêu cầu. Thay vào đó, hãy thực hiện việc cắt giảm trong bộ thực thi của bạn, giữa phản hồi HTTP và mô hình.

KEEP = {
    "getCustomer": ["id", "email", "plan", "status"],
    "listOrders": ["id", "total", "status", "created_at"],
}

def project(tool_name, payload):
    keep = KEEP.get(tool_name)
    if keep is None:
        return payload
    if isinstance(payload, list):
        return [{k: item.get(k) for k in keep if k in item} for item in payload]
    return {k: payload.get(k) for k in keep if k in payload}

Ba cải tiến sau đây giúp điều này khả thi trong thực tế.

id,total,status,created_at
ord_91,4900,paid,2026-08-21
ord_92,1200,refunded,2026-08-22

Quy tắc bốn: tóm tắt trên máy chủ cho các trường hợp nặng

Một số câu hỏi không cần đến bản ghi nào cả. “Khách hàng này có bất kỳ khoản thanh toán thất bại nào trong tháng này không?” là một câu hỏi dạng boolean. Trả về 40 đối tượng thanh toán để mô hình tự xử lý là cách trả lời tốn kém.

Khi một câu hỏi lặp lại, hãy thêm endpoint trả lời trực tiếp câu hỏi đó. Một bản tóm tắt tình trạng tài khoản, một bản tổng hợp trạng thái, một tập hợp nhỏ. Việc này trông giống như công việc thiết kế API thông thường bởi vì nó là như vậy, và đây là phiên bản có giá trị nhất của tất cả những điều trên: thay vì cắt giảm một phản hồi lớn, bạn tránh tạo ra một phản hồi như vậy.

Hai rào cản bảo vệ. Giữ các bản tóm tắt ổn định về hình dạng để các tác nhân có thể dựa vào chúng, và tạo phiên bản cho chúng, bởi vì prompt của một tác nhân được viết dựa trên một hình dạng và một thay đổi âm thầm sẽ làm hỏng nó. Bài viết của chúng tôi về điều gì xảy ra khi API thay đổi bên dưới một tác nhân đề cập đến rủi ro đó, và chiến lược tạo phiên bản API tốt nhất đề cập đến cơ chế.

Đo lường trước và sau

Không điều nào trong số này đáng làm một cách mù quáng. Ba con số sau đây sẽ cho bạn biết vấn đề nằm ở đâu.

Sau đó, thiết kế hình dạng bạn muốn và mô phỏng nó trước khi nhóm API xây dựng. Một máy chủ giả lập trả về phản hồi đã được cắt giảm cho phép bạn đo lường sự cải thiện và xác minh rằng tác nhân vẫn thành công với ít dữ liệu hơn, đây là câu hỏi thực sự quan trọng. Bài viết của chúng tôi về chạy tác nhân với máy chủ giả lập thay vì môi trường sản xuất đề cập đến quy trình làm việc.

Một kết quả tốt trông như thế nào

Một phản hồi thân thiện với tác nhân thì nhỏ gọn, phẳng và trung thực về những gì nó đã bỏ qua:

{
  "customer": { "id": "8812", "email": "dana@example.com", "plan": "pro" },
  "recent_orders": [
    { "id": "ord_91", "total_cents": 4900, "status": "paid" },
    { "id": "ord_92", "total_cents": 1200, "status": "refunded" }
  ],
  "recent_orders_total": 47,
  "truncated": true,
  "_omitted": ["billing_address", "metadata", "order_line_items"]
}

Dưới 200 token. Nó trả lời câu hỏi phổ biến, nó cho biết có 47 đơn hàng thay vì ngụ ý chỉ có hai, và nó cho mô hình biết những gì có thể hỏi tiếp theo.

Bắt đầu với endpoint gây tốn kém nhất của bạn. Đo lường nó, thêm tính năng chọn trường, giới hạn danh sách và chạy lại tác nhân. Khoảng cách giữa hai con số thường đủ lớn để biện minh cho phần còn lại của công việc. Tải xuống Apidog nếu bạn muốn có công cụ đo lường và giả lập trong cùng một dự án.

Ba nơi điều này xuất hiện

Mẫu chung của cả ba trường hợp: tác nhân cần một bề mặt ra quyết định, và API đã cung cấp cho nó một tài liệu.

Bạn cần lịch sử chạy để thấy được mô hình

Một lần chạy duy nhất cho bạn biết rằng một phản hồi lớn. Mô hình, tức là endpoint nào vượt quá ngân sách và tần suất như thế nào, chỉ xuất hiện qua nhiều lần chạy.

Điều đó có nghĩa là các con số phải tồn tại sau phiên làm việc. Đối với một dịch vụ bạn đã triển khai, đó là dữ liệu đo từ xa của riêng bạn. Đối với các tác nhân mã hóa thực hiện công việc được giao, đó là bất kỳ nền tảng nào chạy chúng: Sharkly giữ dấu vết thực thi và kết quả của mỗi lần chạy trên Task mà nó đến từ đó, do đó việc so sánh giữa các lần chạy là vấn đề đọc lịch sử tác vụ chứ không phải tái tạo các phiên terminal. Dù sao đi nữa, việc thực thi ngân sách mà không có lịch sử sẽ cho bạn biết rằng có điều gì đó quá lớn, nhưng không phải là điều cần khắc phục đầu tiên.

Đặt ngân sách cho mỗi công cụ, không chỉ cho mỗi lần chạy

Hầu hết các nhóm giới hạn tổng ngữ cảnh và dừng lại ở đó. Ngân sách cho mỗi công cụ hữu ích hơn, vì nó biến một vấn đề mơ hồ thành một vấn đề cụ thể.

Hãy đặt một giới hạn cho mỗi công cụ, ví dụ 1.500 token. Khi một phản hồi vượt quá giới hạn đó, bộ thực thi sẽ cắt giảm theo phần được chiếu, thêm dấu chỉ trường bị bỏ qua và ghi lại sự tràn bộ nhớ. Bây giờ bạn có một danh sách các endpoint thường xuyên vượt quá ngân sách, được xếp hạng theo tần suất tác nhân gọi chúng, đây chính là hàng đợi công việc của bạn.

Ngân sách cũng bảo vệ bạn khỏi các endpoint nhỏ trong thử nghiệm nhưng lại khổng lồ đối với một khách hàng thực tế. Các phân phối có đuôi, và tài khoản có 4.000 đơn hàng là tài khoản sẽ làm hỏng một lần chạy lúc 2 giờ sáng. Một giới hạn cứng sẽ biến điều đó thành một phản hồi đã cắt giảm thay vì một tác vụ thất bại.

Các câu hỏi thường gặp

Thực hành thiết kế API trong Apidog

Khám phá cách dễ dàng hơn để xây dựng và sử dụng API