会话预算是您在创建会话时设置的可选硬性支出上限。平台会按公开标价持续为会话消耗的所有内容计价(即会话的 list cost(标价成本)),并在该成本达到预算后停止发出新的模型请求。越过上限时正在进行的请求仍会完成,因此最终的标价成本可能会略微超出预算。达到预算的会话会暂停并进入空闲状态,而不是终止;更改或移除预算会恢复因预算而暂停的工作。部署接受相同的预算,并将其应用于其启动的每个会话;请参阅部署上的预算。
在创建会话时设置预算
在创建会话时传入可选的 budget (csharp, go: Budget) 字段:
cURL
curl -sS --fail-with-body https://api.anthropic.com/v1/sessions \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: managed-agents-2026-04-01" \
-H "content-type: application/json" \
-d '{
"agent": "'"$AGENT_ID"'",
"environment_id": "'"$ENVIRONMENT_ID"'",
"budget": {
"type": "limit",
"max_list_cost": {"amount": "125", "currency": "USD"}
}
}'
CLI
# 请保持金额带引号,以便作为字符串而非数字发送。
ant beta:sessions create \
--agent "$AGENT_ID" \
--environment-id "$ENVIRONMENT_ID" \
--budget '{type: limit, max_list_cost: {amount: "125", currency: USD}}'
Python
session = client.beta.sessions.create(
agent=agent.id,
environment_id=environment.id,
budget={
"type": "limit",
"max_list_cost": {"amount": "125", "currency": "USD"},
},
)
print(session.id, session.budget.max_list_cost.amount) # sesn_01... 125
TypeScript
const session = await client.beta.sessions.create({
agent: agent.id,
environment_id: environment.id,
budget: {
type: "limit",
max_list_cost: { amount: "125", currency: "USD" }
}
});
console.log(session.id, session.budget?.max_list_cost.amount); // sesn_01... 125
C#
var session = await client.Beta.Sessions.Create(new()
{
Agent = agent.ID,
EnvironmentID = environment.ID,
Budget = new()
{
MaxListCost = new() { Amount = "125", Currency = BetaCurrency.Usd },
},
});
Console.WriteLine($"{session.ID} {session.Budget?.MaxListCost.Amount}"); // sesn_01... 125
Go
session, err := client.Beta.Sessions.New(ctx, anthropic.BetaSessionNewParams{
Agent: anthropic.BetaSessionNewParamsAgentUnion{
OfString: anthropic.String(agent.ID),
},
EnvironmentID: environment.ID,
Budget: anthropic.BetaManagedAgentsBudgetLimitParam{
MaxListCost: anthropic.BetaMonetaryAmountParam{
Amount: "125",
Currency: anthropic.BetaCurrencyUsd,
},
},
})
if err != nil {
panic(err)
}
fmt.Println(session.ID, session.Budget.MaxListCost.Amount) // sesn_01... 125
Java
var session = client.beta().sessions().create(SessionCreateParams.builder()
.agent(agent.id())
.environmentId(environment.id())
.budget(BetaManagedAgentsBudgetLimit.builder()
.maxListCost(BetaMonetaryAmount.builder()
.amount("125")
.currency(BetaCurrency.USD)
.build())
.build())
.build());
IO.println(session.id() + " " + session.budget().orElseThrow().maxListCost().amount()); // sesn_01... 125
PHP
$session = $client->beta->sessions->create(
agent: $agent->id,
environmentID: $environment->id,
budget: [
'type' => 'limit',
'max_list_cost' => ['amount' => '125', 'currency' => 'USD'],
],
);
echo "{$session->id} {$session->budget->maxListCost->amount}\n"; // sesn_01... 125
Ruby
session = client.beta.sessions.create(
agent: agent.id,
environment_id: environment.id,
budget: {
type: "limit",
max_list_cost: {amount: "125", currency: "USD"}
}
)
puts "#{session.id} #{session.budget.max_list_cost.amount}" # sesn_01... 125
budget (csharp, go: Budget) 对象有两个字段:
type(csharp, go:Type) 始终为"limit"。max_list_cost(java, php:maxListCost; csharp, go:MaxListCost) 是上限本身:amount(csharp, go:Amount) 是以不带前导零的字符串形式表示的美分整数("125"表示 1.25 美元,"50"表示 50 美分),且必须大于零。诸如"25.00"之类的小数形式会被拒绝。金额使用字符串而非数字,因此永远不会对其进行浮点舍入。currency(csharp, go:Currency) 是大写的 ISO-4217 货币代码;USD是唯一支持的货币。
预算只能在创建会话时附加。向没有预算的现有会话添加预算会被拒绝并返回 400 错误。已设预算的会话的上限可以随时更改或移除。
标价成本的计量方式
平台会持续按公开标价费率对会话消耗的内容进行计价:
- 模型令牌,按每个所服务模型的标价计算
- 网页搜索,每 1,000 次搜索 10 美元
- 会话运行时间,每小时 0.08 美元
这一累计美元总额就是会话的标价成本,预算正是与它进行比较。标价成本并非您的合同价格:如果您的组织已协商折扣,会话会在标价总额达到上限时达到上限,而您的实际计费支出可能低于该上限。
强制执行使用精确的、未经舍入的标价成本。会话及其事件上报告的 list_cost (java, php: listCost; csharp, go: ListCost) 数值是四舍五入到最接近美分的整数美分,因此报告的数值与强制执行所用的精确金额之间可能相差最多半美分(偏高或偏低)。
当会话达到其预算时
上限在模型请求之间执行,而不是在请求进行中执行。在每个模型请求之前,平台会检查会话已消耗的标价成本,一旦该总额达到上限,每个线程都会在其下一个请求之前暂停。使总额越过上限的那个请求是在会话仍低于上限时被接纳的,因此会运行至完成。因此,已暂停会话记录的 list_cost (java, php: listCost; csharp, go: ListCost) 会等于或略微超出 max_list_cost (java, php: maxListCost; csharp, go: MaxListCost)。例如,上限为 "50"(50 美分)的会话可能会在 list_cost (java, php: listCost; csharp, go: ListCost) 为 "53" 时暂停。这是预期行为,而不是计费错误。超出上限的模型支出最多为每个线程一个模型请求的成本。该请求响应中的工具调用仍会运行,其网络搜索和运行时间也会计入标价成本。请将预算视为对新工作的限制,而不是精确的停止点,并在设定上限时考虑到这一余量。
达到预算的会话会进入空闲状态,其 stop_reason (java, php: stopReason; csharp, go: StopReason) 为 budget_reached;它不会被终止,其历史记录和沙箱会像其他任何空闲会话一样被保留。在事件流上,您将依次看到:
- 每个线程暂停时,一个
stop_reason(java, php:stopReason; csharp, go:StopReason) 为budget_reached的session.thread_status_idle事件。 - 一个
session.usage事件,包含会话的累计用量和标价成本。 - 一个
stop_reason(java, php:stopReason; csharp, go:StopReason) 为budget_reached的session.status_idle事件。用量事件总是紧接在此空闲事件之前。
如果有打开的工作流运行,每个尚未空闲的运行也会收到一个 workflow_run.status_idle 事件。
如果某个线程的最后一次请求既越过了上限又完成了其轮次,该线程会在自己的 session.thread_status_idle 事件上报告 end_turn,而会话仍报告 budget_reached;请将会话级别的 stop_reason (java, php: stopReason; csharp, go: StopReason) 视为会话因达到预算而暂停的信号。
达到上限时接受的事件
当会话达到或超过其预算时,它只接受用于结算已在进行中的工作的事件:
user.tool_confirmationuser.tool_resultuser.custom_tool_resultuser.interrupt
任何会启动新工作的事件(例如 user.message)都会被拒绝,并返回列出此列表的 400 错误。已结算的结果会被记录,而不会触发新的模型请求;会话保持在其预算处暂停。
在会话因达到预算而暂停时(所有线程都在上限处暂停)发送的 user.interrupt 会被接受,并且不会出现在事件列表中。它不会停止任何线程,因为每个线程都已暂停。请更改或移除预算以继续。
如果会话有打开的工作流运行,中断可以暂停它们,就像在其他任何时候的中断一样。被中断暂停的运行在您更改或移除预算时不会恢复。要继续该运行,请更改或移除预算,然后发送一条 user.message,要求智能体继续其运行。请参阅在有运行打开时中断会话。
恢复达到预算的会话
通过会话更新来更改或移除预算。被接受的更新会自动恢复被预算暂停的工作;无需客户端执行进一步操作。
每个被预算暂停的工作流运行也会收到一个 workflow_run.status_running 事件。被中断暂停的运行,即使该中断是在会话达到预算时发送的,也会保持暂停,并且不会因该更新而收到 workflow_run.status_running 事件。要继续该运行,请发送一条 user.message,要求智能体继续其运行。请参阅在有打开的运行时中断会话。
更改预算
使用新的 max_list_cost (java, php: maxListCost; csharp, go: MaxListCost) 更新会话。新值可以高于或低于当前上限,但必须严格大于会话已消耗的标价成本;否则更新会被拒绝,并返回 400 错误:budget.max_list_cost must be greater than the session's consumed list cost。由于会话暂停时已消耗的成本通常会略微超出旧上限,请根据会话报告的 usage.list_cost (java, php: usage.listCost; csharp, go: Usage.ListCost) 而不是旧的 max_list_cost (java, php: maxListCost; csharp, go: MaxListCost) 来确定新值。请将其设置为比该数值高出一美分或更多:报告的值经过舍入,可能略低于检查所用的精确已消耗成本。
cURL
curl -sS --fail-with-body "https://api.anthropic.com/v1/sessions/$SESSION_ID" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: managed-agents-2026-04-01" \
-H "content-type: application/json" \
-d '{
"budget": {
"type": "limit",
"max_list_cost": {"amount": "500", "currency": "USD"}
}
}'
CLI
ant beta:sessions update \
--session-id "$SESSION_ID" \
--budget '{type: limit, max_list_cost: {amount: "500", currency: USD}}'
Python
updated_session = client.beta.sessions.update(
session.id,
budget={
"type": "limit",
"max_list_cost": {"amount": "500", "currency": "USD"},
},
)
print(updated_session.budget.max_list_cost.amount) # 500
TypeScript
const updatedSession = await client.beta.sessions.update(session.id, {
budget: {
type: "limit",
max_list_cost: { amount: "500", currency: "USD" }
}
});
console.log(updatedSession.budget?.max_list_cost.amount); // 500
C#
var updatedSession = await client.Beta.Sessions.Update(session.ID, new()
{
Budget = new()
{
MaxListCost = new() { Amount = "500", Currency = BetaCurrency.Usd },
},
});
Console.WriteLine(updatedSession.Budget?.MaxListCost.Amount); // 500
Go
updatedSession, err := client.Beta.Sessions.Update(ctx, session.ID, anthropic.BetaSessionUpdateParams{
Budget: anthropic.BetaManagedAgentsBudgetLimitParam{
MaxListCost: anthropic.BetaMonetaryAmountParam{
Amount: "500",
Currency: anthropic.BetaCurrencyUsd,
},
},
})
if err != nil {
panic(err)
}
fmt.Println(updatedSession.Budget.MaxListCost.Amount) // 500
Java
var updatedSession = client.beta().sessions().update(session.id(), SessionUpdateParams.builder()
.budget(BetaManagedAgentsBudgetLimit.builder()
.maxListCost(BetaMonetaryAmount.builder()
.amount("500")
.currency(BetaCurrency.USD)
.build())
.build())
.build());
IO.println(updatedSession.budget().orElseThrow().maxListCost().amount()); // 500
PHP
$updatedSession = $client->beta->sessions->update(
$session->id,
budget: [
'type' => 'limit',
'max_list_cost' => ['amount' => '500', 'currency' => 'USD'],
],
);
echo "{$updatedSession->budget->maxListCost->amount}\n"; // 500
Ruby
updated_session = client.beta.sessions.update(
session.id,
budget: {
type: "limit",
max_list_cost: {amount: "500", currency: "USD"}
}
)
puts updated_session.budget.max_list_cost.amount # 500
移除预算
传入 "budget": null (python: budget=None; typescript: budget: null; ruby: budget: nil; go: Budget: param.NullStruct[anthropic.BetaManagedAgentsBudgetLimitParam](); java: .budget(Optional.empty()); csharp: Budget = null; php: requestOptions: ['extraBodyParams' => ['budget' => null]]; cli: --budget null) 以完全移除上限。被预算暂停的工作会恢复,随之产生的 session.updated 事件中 budget (csharp, go: Budget) 被设置为 null。
cURL
curl -sS --fail-with-body "https://api.anthropic.com/v1/sessions/$SESSION_ID" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: managed-agents-2026-04-01" \
-H "content-type: application/json" \
-d '{"budget": null}'
CLI
ant beta:sessions update --session-id "$SESSION_ID" --budget null
Python
unbudgeted_session = client.beta.sessions.update(session.id, budget=None)
print(unbudgeted_session.budget) # None
TypeScript
const unbudgetedSession = await client.beta.sessions.update(session.id, { budget: null });
console.log(unbudgetedSession.budget); // null
C#
// 赋值为 null 会发送显式的 null;不设置 Budget 则会省略该字段。
var unbudgetedSession = await client.Beta.Sessions.Update(session.ID, new() { Budget = null });
Console.WriteLine(unbudgetedSession.Budget is null); // True: the session no longer has a budget
Go
// 零值 Budget 会从请求中省略;param.NullStruct(来自
// github.com/anthropics/anthropic-sdk-go/v2/packages/param)会发送显式的 null。
unbudgetedSession, err := client.Beta.Sessions.Update(ctx, session.ID, anthropic.BetaSessionUpdateParams{
Budget: param.NullStruct[anthropic.BetaManagedAgentsBudgetLimitParam](),
})
if err != nil {
panic(err)
}
fmt.Println(unbudgetedSession.JSON.Budget.Valid()) // false: the session no longer has a budget
Java
// 空的 Optional 会发送显式的 null;不设置 budget 则会省略该字段。
var unbudgetedSession = client.beta().sessions().update(session.id(), SessionUpdateParams.builder()
.budget(Optional.empty())
.build());
IO.println(unbudgetedSession.budget().isPresent()); // false: the session no longer has a budget
PHP
// update(budget: null) 会省略该字段,因此需将显式的 null 作为额外的请求体参数发送。
$unbudgetedSession = $client->beta->sessions->update(
$session->id,
requestOptions: ['extraBodyParams' => ['budget' => null]],
);
echo json_encode($unbudgetedSession->budget), "\n"; // null
Ruby
unbudgeted_session = client.beta.sessions.update(session.id, budget: nil)
p unbudgeted_session.budget # nil
警告
移除会话的预算是单向操作:预算已被移除的会话无法再被赋予新的预算。若要保留会话的上限,请改为更改预算。
监控支出
会话对象包含其 budget (csharp, go: Budget) 以及一个记录所跟踪支出的 usage (csharp, go: Usage) 对象:usage.list_cost (java, php: usage.listCost; csharp, go: Usage.ListCost) 是会话已消耗的标价成本,usage.active_seconds (java, php: usage.activeSeconds; csharp, go: Usage.ActiveSeconds) 是用于计算其运行时成本的运行时间。对于在 budget_reached 处暂停的会话,usage.list_cost (java, php: usage.listCost; csharp, go: Usage.ListCost) 预计会等于或略微超出 max_list_cost (java, php: maxListCost; csharp, go: MaxListCost):越过上限的请求在暂停之前已完成。会话级别的 active_seconds (java, php: activeSeconds; csharp, go: ActiveSeconds) 对并发线程的重叠活动只计算一次。线程检索响应在线程自身的 usage (csharp, go: Usage) 上包含相同的两个字段,按每个线程计价。每个线程的数值是独立舍入的,且不包括会话的运行时间成本,因此它们的总和并不完全等于会话的 list_cost (java, php: listCost; csharp, go: ListCost);预算所依据执行的是会话级别的数值。
session.usage 事件是会话累计用量和所跟踪标价成本的快照。它包含会话的令牌总数、list_cost (java, php: listCost; csharp, go: ListCost)、active_seconds (java, php: activeSeconds; csharp, go: ActiveSeconds)、server_tool_use (java, php: serverToolUse; csharp, go: ServerToolUse) 请求计数(web_search_requests (java, php: webSearchRequests; csharp, go: WebSearchRequests),按请求计入标价成本;以及 web_fetch_requests (java, php: webFetchRequests; csharp, go: WebFetchRequests),其值为 0,因为网页获取请求不按请求收费,也不计量),以及会话的 budget (csharp, go: Budget)(如果会话设置了预算)。它会出现在事件列表和会话流中。无论停止原因是什么,会话都会在进入空闲状态之前立即发出一个该事件,因此达到预算的会话总会在预算已达到的空闲事件之前立即发出一个该事件。
要从流和会话对象中读取用量,请参阅跟踪用量。
多智能体会话中的预算
多智能体会话只有一个由其所有线程共享的预算;没有按线程设置的上限。每个线程的消耗按其自身所服务的模型计价,并且在达到共享上限时各线程独立暂停。顾问咨询按顾问模型的费率计价,并计入同一预算。一个线程可能在 budget_reached 处暂停,而另一个线程仍在完成其进行中的请求。
待处理的询问优先于上限:若会话中一个线程在等待 requires_action,另一个线程在 budget_reached 处暂停,则会话级别报告 requires_action。待处理的请求仍需要回答,而回答它属于预算不会阻止的结算事件。
部署上的预算
部署在您创建或更新它时接受相同的 budget 对象:
{
"budget": {
"type": "limit",
"max_list_cost": { "amount": "2000", "currency": "USD" }
}
}
上限会被复制到部署启动的每个会话上,因此它分别限制每次运行,而不是部署的累计支出。更改部署的预算会应用于部署此后启动的会话,而不会应用于已在运行的会话。与会话不同,部署的预算可以通过 "budget": null (python: budget=None; typescript: budget: null; ruby: budget: nil; go: Budget: param.NullStruct[anthropic.BetaManagedAgentsBudgetLimitParam](); java: .budget(Optional.empty()); csharp: Budget = null; php: requestOptions: ['extraBodyParams' => ['budget' => null]]; cli: --budget null) 清除,并在之后重新设置。请参阅为每次运行设置预算。
没有标价的模型
预算只能跟踪平台可以计价的消耗。如果以下任一项使用了没有公开标价的模型,创建设有预算的会话会被拒绝,并返回 400 错误:
- 会话的智能体
subagents(csharp, go:Subagents) 或workflows(csharp, go:Workflows) 的predefined_agents(java, php:predefinedAgents; csharp, go:PredefinedAgents) 列表中列出的任何智能体- 智能体的多智能体配置中设置的顾问
错误会说明该模型没有可用的标价。
如果设置了预算的会话的用量中出现了没有标价的模型,预算将无法再计量该会话的支出:会话可能会以 budget_reached 作为 stop_reason (java, php: stopReason; csharp, go: StopReason) 暂停,并且更改预算会被拒绝。请移除预算以恢复会话。
错误参考
与预算相关的请求在以下情况下会被拒绝:
| 条件 | 状态 |
|---|---|
在会话达到或超过其预算时发送了启动工作的事件(例如 user.message);错误会列出接受的结算事件 |
400 |
| 预算被设置为等于或低于会话已消耗标价成本的值 | 400 |
| 向创建时没有预算的会话添加预算,或在移除后重新添加 | 400 |
amount (csharp, go: Amount) 不是整数美分(例如 "25.00")、为零或负数,或 currency (csharp, go: Currency) 不是 USD |
400 |
| 已设预算的创建引用了没有公开标价的模型 | 400 |
注意
会话预算是针对单个会话的、以美元计(以美分书写)的硬性上限,由平台强制执行。它们不同于 Messages API 的任务预算,后者是建议性的、以令牌计量的预算,供模型在单个智能体循环内进行自我调节。
可用性
会话预算在所有模型上处于 beta 阶段。
API 支持
Messages API
- 可用性:不可用
- 用法:请改用任务预算。
Managed Agents
- 可用性:可用
| 状态 | 云平台 |
|---|---|
| Beta | 所有支持的平台 |
所需的 beta 请求头
Beta 请求头让您可以在实验性功能和新模型能力成为标准 API 的一部分之前访问它们。
managed-agents-2026-04-01
数据处理
| 项目 | 零数据保留 | HIPAA |
|---|---|---|
| 状态 | 不具备资格 | 不具备资格 |
| 详细信息 | 会话是有状态的资源;对话记录会一直保留,直到您将其删除。适用于所有 Managed Agents 子功能,包括自托管沙箱。 | 适用于所有 Managed Agents 子功能,包括自托管沙箱。 |
适用的端点:
/v1/agents/v1/sessions/v1/environments