어드바이저 도구
어드바이저 도구 (Advisor tool)
어드바이저 도구는 더 빠르고 저렴한 실행자 모델(executor model) 이 생성 도중에 더 높은 지능의 어드바이저 모델(advisor model) 을 참고해 전략적 지침을 얻을 수 있게 해줘요. 어드바이저는 전체 대화를 읽고 계획이나 방향 수정을 만들어내며, 실행자는 작업을 계속해요.
출처: 문서
본문
어드바이저 도구는 더 빠르고 비용이 낮은 실행자 모델이 생성 도중 더 높은 지능의 어드바이저 모델을 참고해 전략적 지침을 얻을 수 있게 해줘요. 어드바이저는 전체 대화를 읽고 계획이나 방향 수정을 만들어내며, 실행자는 그 지침을 바탕으로 작업을 계속해요.
이 패턴은 대부분의 턴이 기계적이지만 훌륭한 계획이 결정적인 장기 지평 에이전트 작업(코딩 에이전트, computer use, 다단계 연구 파이프라인)에 어울려요. 어드바이저 단독 품질에 근접하면서도 토큰 생성의 대부분은 실행자 모델 요금으로 일어나요. 실행자의 자체 능력이 어드바이저에 가까워질수록 이득이 줄어드는 측정 결과를 포함해 비용과 지능 최적화하기를 참고하세요.
sequenceDiagram
participant U as Your application
participant E as Executor model
participant A as Advisor model
U->>E: Request with advisor tool
note over E: Executor begins the task
E->>A: server_tool_use (server-side)
note over A: Reads the full transcript,<br/>returns strategic guidance
A-->>E: advisor_tool_result
note over E: Executor continues,<br/>informed by the advice
E-->>U: Response
참고 (Note) 이 기능에 제로 데이터 보존(ZDR)이 어떻게 적용되는지는 API 및 데이터 보존을 참고하세요.
언제 사용해야 하나 (When to use it)
어드바이저는 이런 구성에 어울려요:
- 현재 복잡한 작업에 Sonnet을 쓰고 있다면: 더 높은 티어의 어드바이저를 추가하세요. Opus는 총 비용을 비슷하거나 더 낮게 유지해요. Claude Fable 5.1은 품질 향상을 극대화해요.
- 현재 Haiku를 쓰고 한 단계 더 지능을 높이고 싶다면: Opus 또는 Fable 어드바이저를 추가하세요. Haiku 단독보다 비용은 높겠지만, 실행자를 더 큰 모델로 바꾸는 것보다는 낮아요.
결과는 작업에 따라 달라져요. 자체 워크로드에서 평가하세요.
어드바이저는 단일 턴 Q&A(계획할 것이 없음), 사용자가 이미 자신의 비용과 품질 트레이드오프를 고르는 순수 통과형 모델 선택기, 또는 모든 턴이 진정으로 어드바이저 모델의 완전한 능력을 필요로 하는 워크로드에는 덜 어울려요.
빠른 시작 (Quick start)
참고 (Note) 어드바이저 도구는 베타예요. 요청에 베타 헤더
advisor-tool-2026-03-01을 포함하세요.
ant beta:messages create --beta advisor-tool-2026-03-01 <<'YAML'
model: claude-sonnet-5
max_tokens: 4096
tools:
- type: advisor_20260301
name: advisor
model: claude-opus-5
messages:
- role: user
content: Build a concurrent worker pool in Go with graceful shutdown.
YAML
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-sonnet-5",
max_tokens=4096,
betas=["advisor-tool-2026-03-01"],
tools=[
{
"type": "advisor_20260301",
"name": "advisor",
"model": "claude-opus-5",
}
],
messages=[
{
"role": "user",
"content": "Build a concurrent worker pool in Go with graceful shutdown.",
}
],
)
print(response)
const client = new Anthropic();
const response = await client.beta.messages.create({
model: "claude-sonnet-5",
max_tokens: 4096,
betas: ["advisor-tool-2026-03-01"],
tools: [
{
type: "advisor_20260301",
name: "advisor",
model: "claude-opus-5"
}
],
messages: [
{
role: "user",
content: "Build a concurrent worker pool in Go with graceful shutdown."
}
]
});
console.log(response);
using Anthropic.Models.Beta.Messages;
using Messages = Anthropic.Models.Messages;
var client = new AnthropicClient();
var parameters = new MessageCreateParams
{
Model = Messages::Model.ClaudeSonnet5,
MaxTokens = 4096,
Tools = new BetaToolUnion[]
{
new BetaAdvisorTool20260301
{
Model = Messages::Model.ClaudeOpus5
}
},
Messages =
[
new BetaMessageParam
{
Role = Role.User,
Content = "Build a concurrent worker pool in Go with graceful shutdown."
}
],
Betas = ["advisor-tool-2026-03-01"]
};
var response = await client.Beta.Messages.Create(parameters);
Console.WriteLine(response);
client := anthropic.NewClient()
response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
Model: anthropic.ModelClaudeSonnet5,
MaxTokens: 4096,
Tools: []anthropic.BetaToolUnionParam{
{OfAdvisorTool20260301: &anthropic.BetaAdvisorTool20260301Param{
Model: anthropic.ModelClaudeOpus5,
}},
},
Messages: []anthropic.BetaMessageParam{
anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Build a concurrent worker pool in Go with graceful shutdown.")),
},
Betas: []anthropic.AnthropicBeta{
anthropic.AnthropicBetaAdvisorTool2026_03_01,
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(response)
import com.anthropic.models.beta.messages.BetaAdvisorTool20260301;
import com.anthropic.models.beta.messages.BetaMessage;
import com.anthropic.models.beta.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;
void main() {
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.CLAUDE_SONNET_5)
.maxTokens(4096L)
.addTool(BetaAdvisorTool20260301.builder()
.model(Model.CLAUDE_OPUS_5)
.build())
.addUserMessage("Build a concurrent worker pool in Go with graceful shutdown.")
.addBeta("advisor-tool-2026-03-01")
.build();
BetaMessage response = client.beta().messages().create(params);
IO.println(response);
}
$client = new Client();
$response = $client->beta->messages->create(
maxTokens: 4096,
messages: [
[
'role' => 'user',
'content' => 'Build a concurrent worker pool in Go with graceful shutdown.',
],
],
model: 'claude-sonnet-5',
tools: [
[
'type' => 'advisor_20260301',
'name' => 'advisor',
'model' => 'claude-opus-5',
],
],
betas: ['advisor-tool-2026-03-01'],
);
echo $response;
client = Anthropic::Client.new
response = client.beta.messages.create(
model: "claude-sonnet-5",
max_tokens: 4096,
tools: [
{
type: "advisor_20260301",
name: "advisor",
model: "claude-opus-5"
}
],
messages: [
{
role: "user",
content: "Build a concurrent worker pool in Go with graceful shutdown."
}
],
betas: ["advisor-tool-2026-03-01"]
)
puts response
응답 content에는 어드바이저의 지침을 담은 advisor_tool_result 블록이 포함돼요. 이 빠른 시작처럼 claude-opus-5를 어드바이저로 쓰면 블록의 content 필드는 advisor_redacted_result 변형(암호화됨. 실행자는 서버 측에서 읽을 수 있지만 여러분의 클라이언트는 못 읽어요)이에요. 응답에서 지침 텍스트를 직접 보려면 어드바이저 모델로 claude-opus-4-8을 대신 사용하세요. 그러면 평문 advisor_result 변형이 반환돼요. 두 형태를 나란히 보려면 결과 변형을, 어떤 어드바이저 모델이 무엇을 반환하는지와 유효 쌍 전체 목록은 모델 호환성을 참고하세요.
작동 방식 (How it works)
tools 배열에 어드바이저 도구를 추가하면 실행자 모델은 다른 도구처럼 언제 호출할지 결정해요. 실행자가 어드바이저를 호출하면:
- 실행자가
name: "advisor"와 빈input을 가진server_tool_use블록을 만들어내요. 실행자가 타이밍을 신호하고 서버가 컨텍스트를 제공해요. - Anthropic이 서버 측에서 어드바이저 모델에 별도의 추론 패스를 실행해요. 어드바이저는 자체 Anthropic 제공 시스템 프롬프트 아래에서 실행되며, 실행자의 전체 트랜스크립트를 그 입력의 인용된 컨텍스트로 받아요. 그 트랜스크립트에는 여러분의 시스템 프롬프트, 도구 정의, 이전 턴과 도구 결과, 그리고 이번 턴에서 실행자가 지금까지 만든 텍스트가 포함돼요.
- 어드바이저의 응답이
advisor_tool_result블록으로 실행자에게 돌아와요. - 실행자가 그 지침을 바탕으로 생성을 계속해요.
이 모든 것은 단일 /v1/messages 요청 안에서 일어나며 여러분 쪽의 추가 왕복은 없어요. 예외는 호출 중간에 일시 중지되는 턴으로, 이후 요청으로 재개해요. (일시 중지된 턴 재개하기 참고)
어드바이저 자체는 도구 없이, 컨텍스트 관리 없이 실행돼요. 그 thinking 블록은 결과가 반환되기 전에 버려져요. 지침 텍스트만 실행자에게 도달해요.
도구 파라미터 (Tool parameters)
| 파라미터 | 타입 | 기본값 | 설명 |
|---|---|---|---|
type |
string | 필수 | "advisor_20260301"이어야 해요. |
name |
string | 필수 | "advisor"이어야 해요. |
model |
string | 필수 | 어드바이저 모델 ID(예: claude-opus-5). 하위 추론에 대해 이 모델의 요금이 청구돼요. |
max_uses |
integer | 무제한 | 단일 요청에서 허용되는 최대 어드바이저 호출 수. 실행자가 이 한도에 도달하면 이후 어드바이저 호출은 error_code: "max_uses_exceeded"를 가진 advisor_tool_result_error를 반환하고 실행자는 더 이상의 지침 없이 계속해요. 이것은 요청당 한도이지 대화당 한도가 아니에요. 대화 수준 제한은 비용 통제를 참고하세요. |
max_tokens |
integer | 어드바이저 모델 출력 한도 | 호출당 어드바이저 총 출력(thinking + 텍스트)을 제한. 최소 1024. 어드바이저 출력 제한하기를 참고하세요. |
caching |
object | null | null (끔) |
한 대화 안의 호출들에 걸쳐 어드바이저 자체 트랜스크립트에 프롬프트 캐싱을 활성화해요. 어드바이저 프롬프트 캐싱을 참고하세요. |
caching 객체는 {"type": "ephemeral", "ttl": "5m" | "1h"} 형태예요. 콘텐츠 블록의 cache_control과 달리 이것은 중단점 표시자가 아니에요. 켜기/끄기 스위치예요. 서버가 캐시 경계를 어디에 둘지 결정해요.
어드바이저 도구는 또한 어떤 도구 정의에든 있는 일반 속성인 cache_control, allowed_callers, defer_loading, strict를 받아요. (구조화된 출력에서 다룸) 그것들의 의미는 도구 레퍼런스를 참고하세요.
응답 구조 (Response structure)
성공적인 어드바이저 호출 (Successful advisor call)
어드바이저가 호출되면 어시스턴트의 콘텐츠에 server_tool_use 블록 뒤에 advisor_tool_result 블록이 따라와요. 다음 예시는 Claude Opus 4.8 어드바이저가 반환하는 평문 advisor_result 변형을 보여줘요. 빠른 시작은 Claude Opus 5를 사용하며, 이는 암호화된 advisor_redacted_result 변형을 대신 반환해요. 두 형태를 나란히 보려면 결과 변형을 참고하세요.
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "Let me consult the advisor on this."
},
{
"type": "server_tool_use",
"id": "srvtoolu_abc123",
"name": "advisor",
"input": {}
},
{
"type": "advisor_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "advisor_result",
"text": "Use a channel-based coordination pattern. The tricky part is draining in-flight work during shutdown: close the input channel first, then wait on a WaitGroup..."
}
},
{
"type": "text",
"text": "Here's the implementation. I'm using a channel-based coordination pattern to avoid writer starvation..."
}
]
}
server_tool_use.input은 항상 비어 있어요. 서버가 전체 트랜스크립트에서 어드바이저의 관점을 자동으로 구성해요. 실행자가 input에 넣는 어떤 것도 어드바이저에 도달하지 않아요.
결과 변형 (Result variants)
advisor_tool_result.content 필드는 판별 유니온이에요. 성공적인 호출의 경우 변형은 어드바이저 모델에 따라 달라져요:
| 변형 | 필드 | 반환되는 경우 |
|---|---|---|
advisor_result |
text, stop_reason |
어드바이저 모델이 평문을 반환해요 (예: Claude Opus 4.8). |
advisor_redacted_result |
encrypted_content, stop_reason |
어드바이저 모델이 암호화된 출력을 반환해요. |
참고 (Note) Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5, Claude Fable 5, Claude Mythos 5 어드바이저는 암호화된
advisor_redacted_result를 반환해요. 호환성 표의 다른 모든 어드바이저 모델은 평문advisor_result를 반환해요. 자신의 응답에서 지침 텍스트를 읽으려면claude-opus-4-8처럼 평문을 반환하는 어드바이저를 사용하세요. 단, 호환성 표의 실행자 행에 하나가 나열된 경우에만요. Claude Fable 5.1, Claude Mythos 5.1, Claude Opus 5, Claude Fable 5, Claude Mythos 5 실행자는 암호화된 형태를 반환하는 어드바이저와만 짝을 이루므로, 그 실행자들에서는 지침 텍스트를 응답에서 읽을 수 없어요.
동일한 요청을 두 번 보낸 다음의 예는 도구 정의의 어드바이저 model만 빼고 동일하며, 두 변형을 모두 보여줘요.
"model": "claude-opus-4-8"로 지침은 평문이에요:
{
"type": "advisor_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "advisor_result",
"text": "Use a channel-based coordination pattern. The tricky part is draining in-flight work during shutdown: close the input channel first, then wait on a WaitGroup..."
}
}
"model": "claude-opus-5"로 지침은 암호화돼요:
{
"type": "advisor_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "advisor_redacted_result",
"encrypted_content": "EqQBCkYIBRgCIiQ5ZjE0N2M2OC0yYWIxLTRkZTktYjA3ZC1hZTUyMzkxYjhkMmU..."
}
}
두 결과 변형 모두 도구 정의에 max_tokens를 설정하면 stop_reason 필드를 담고, 설정하지 않으면 생략해요. 이는 어드바이저 하위 호출의 중지 이유를 담으며, 보통 "end_turn"이거나 한도에 도달하면 "max_tokens"예요. 값은 최상위 Messages API stop_reason과 일치해요.
advisor_result에서는 text 필드가 사람이 읽을 수 있는 지침을 담아요. advisor_redacted_result에서는 encrypted_content 필드가 읽을 수 없는 불투명한 blob을 담아요. 다음 턴에 서버가 그것을 복호화해 평문을 실행자의 프롬프트로 렌더링해요.
두 경우 모두 콘텐츠를 이후 턴에 그대로 왕복시키세요. 대화 도중 어드바이저 모델을 바꾸면 두 형태를 모두 처리하도록 content.type으로 분기하세요.
오류 결과 (Error results)
어드바이저 호출이 실패하면 결과가 오류를 담아요:
{
"type": "advisor_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "advisor_tool_result_error",
"error_code": "overloaded"
}
}
실행자는 오류를 보고 더 이상의 지침 없이 계속해요. 요청 자체는 실패하지 않아요.
error_code |
의미 |
|---|---|
max_uses_exceeded |
요청이 도구 정의에 설정된 max_uses 한도에 도달했어요. 같은 요청에서 이후의 어드바이저 호출은 이 오류를 반환해요. |
too_many_requests |
어드바이저 하위 추론이 요금 제한을 받았어요. |
overloaded |
어드바이저 하위 추론이 용량 한도에 도달했어요. |
prompt_too_long |
트랜스크립트가 어드바이저 모델의 컨텍스트 창을 초과했어요. |
execution_time_exceeded |
어드바이저 하위 추론이 시간 초과됐어요. |
model_not_found |
구성된 어드바이저 모델을 사용할 수 없어요. |
unavailable |
기타 어드바이저 실패. |
어드바이저 요금 제한은 어드바이저 모델에 대한 직접 호출과 같은 모델별 버킷에서 가져와요. 어드바이저의 요금 제한은 도구 결과 안에서 too_many_requests로 나타나요. 실행자의 요금 제한은 전체 요청을 HTTP 429로 실패시켜요.
다중 턴 대화 (Multi-turn conversations)
이후 턴에 advisor_tool_result 블록을 포함한 전체 어시스턴트 콘텐츠를 API에 다시 전달하세요. 결과 블록을 그대로 왕복시키세요. Claude Opus 5 어드바이저에서 결과 블록의 content는 암호화된 advisor_redacted_result 변형이고, 서버가 그것을 복호화해 다음 턴에 지침을 실행자 프롬프트로 렌더링해요. (결과 변형 참고) 메커니즘은 어떤 어드바이저 모델이든 동일해요.
tools = [ { "type": "advisor_20260301", "name": "advisor", "model": "claude-opus-5", } ]
messages = [ { "role": "user", "content": "Build a concurrent worker pool in Go with graceful shutdown.", } ]
response = client.beta.messages.create( model="claude-sonnet-5", max_tokens=1024, betas=["advisor-tool-2026-03-01"], tools=tools, messages=messages, )
Append the full response content, including any advisor_tool_result blocks
messages.append({"role": "assistant", "content": response.content})
Continue the conversation
messages.append({"role": "user", "content": "Now add a max-in-flight limit of 10."})
response = client.beta.messages.create( model="claude-sonnet-5", max_tokens=1024, betas=["advisor-tool-2026-03-01"], tools=tools, messages=messages, )
```typescript TypeScript
const client = new Anthropic();
const tools: Anthropic.Beta.Messages.BetaToolUnion[] = [
{
type: "advisor_20260301",
name: "advisor",
model: "claude-opus-5"
}
];
const messages: Anthropic.Beta.Messages.BetaMessageParam[] = [
{
role: "user",
content: "Build a concurrent worker pool in Go with graceful shutdown."
}
];
const response = await client.beta.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
betas: ["advisor-tool-2026-03-01"],
tools,
messages
});
// Append the full response content, including any advisor_tool_result blocks
messages.push({ role: "assistant", content: response.content });
// Continue the conversation
messages.push({ role: "user", content: "Now add a max-in-flight limit of 10." });
const followUp = await client.beta.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
betas: ["advisor-tool-2026-03-01"],
tools,
messages
});
using Anthropic.Models.Beta.Messages;
using Messages = Anthropic.Models.Messages;
var client = new AnthropicClient();
var tools = new BetaToolUnion[]
{
new BetaAdvisorTool20260301 { Model = Messages::Model.ClaudeOpus5 }
};
var messages = new List<BetaMessageParam>
{
new() { Role = Role.User, Content = "Build a concurrent worker pool in Go with graceful shutdown." }
};
var response = await client.Beta.Messages.Create(new MessageCreateParams
{
Model = Messages::Model.ClaudeSonnet5,
MaxTokens = 1024,
Tools = tools,
Messages = messages,
Betas = ["advisor-tool-2026-03-01"]
});
// Append the full response content, including any advisor_tool_result blocks
messages.Add(new BetaMessageParam
{
Role = Role.Assistant,
Content = response.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList()
});
// Continue the conversation
messages.Add(new BetaMessageParam { Role = Role.User, Content = "Now add a max-in-flight limit of 10." });
var followUp = await client.Beta.Messages.Create(new MessageCreateParams
{
Model = Messages::Model.ClaudeSonnet5,
MaxTokens = 1024,
Tools = tools,
Messages = messages,
Betas = ["advisor-tool-2026-03-01"]
});
client := anthropic.NewClient()
tools := []anthropic.BetaToolUnionParam{
{OfAdvisorTool20260301: &anthropic.BetaAdvisorTool20260301Param{
Model: anthropic.ModelClaudeOpus5,
}},
}
messages := []anthropic.BetaMessageParam{
anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Build a concurrent worker pool in Go with graceful shutdown.")),
}
response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
Model: anthropic.ModelClaudeSonnet5,
MaxTokens: 1024,
Tools: tools,
Messages: messages,
Betas: []anthropic.AnthropicBeta{
anthropic.AnthropicBetaAdvisorTool2026_03_01,
},
})
if err != nil {
log.Fatal(err)
}
// Append the full response content, including any advisor_tool_result blocks.
messages = append(messages, response.ToParam())
// Continue the conversation
messages = append(messages, anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Now add a max-in-flight limit of 10.")))
response, err = client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
Model: anthropic.ModelClaudeSonnet5,
MaxTokens: 1024,
Tools: tools,
Messages: messages,
Betas: []anthropic.AnthropicBeta{
anthropic.AnthropicBetaAdvisorTool2026_03_01,
},
})
if err != nil {
log.Fatal(err)
}
import com.anthropic.models.beta.messages.BetaAdvisorTool20260301;
import com.anthropic.models.beta.messages.BetaContentBlock;
import com.anthropic.models.beta.messages.BetaMessage;
import com.anthropic.models.beta.messages.BetaMessageParam;
import com.anthropic.models.beta.messages.BetaToolUnion;
import com.anthropic.models.beta.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;
void main() {
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
List<BetaToolUnion> tools = List.of(
BetaToolUnion.ofAdvisorTool20260301(
BetaAdvisorTool20260301.builder().model(Model.CLAUDE_OPUS_5).build()));
List<BetaMessageParam> messages = new ArrayList<>();
messages.add(BetaMessageParam.builder()
.role(BetaMessageParam.Role.USER)
.content("Build a concurrent worker pool in Go with graceful shutdown.")
.build());
BetaMessage response = client.beta().messages().create(MessageCreateParams.builder()
.model(Model.CLAUDE_SONNET_5)
.maxTokens(1024L)
.tools(tools)
.messages(messages)
.addBeta("advisor-tool-2026-03-01")
.build());
// Append the full response content, including any advisor_tool_result blocks
messages.add(BetaMessageParam.builder()
.role(BetaMessageParam.Role.ASSISTANT)
.contentOfBetaContentBlockParams(
response.content().stream().map(BetaContentBlock::toParam).toList())
.build());
// Continue the conversation
messages.add(BetaMessageParam.builder()
.role(BetaMessageParam.Role.USER)
.content("Now add a max-in-flight limit of 10.")
.build());
BetaMessage followUp = client.beta().messages().create(MessageCreateParams.builder()
.model(Model.CLAUDE_SONNET_5)
.maxTokens(1024L)
.tools(tools)
.messages(messages)
.addBeta("advisor-tool-2026-03-01")
.build());
}
$client = new Client();
$tools = [
[
'type' => 'advisor_20260301',
'name' => 'advisor',
'model' => 'claude-opus-5',
],
];
$messages = [
[
'role' => 'user',
'content' => 'Build a concurrent worker pool in Go with graceful shutdown.',
],
];
$response = $client->beta->messages->create(
maxTokens: 1024,
messages: $messages,
model: 'claude-sonnet-5',
tools: $tools,
betas: ['advisor-tool-2026-03-01'],
);
// Append the full response content, including any advisor_tool_result blocks
$messages[] = ['role' => 'assistant', 'content' => $response->content];
// Continue the conversation
$messages[] = ['role' => 'user', 'content' => 'Now add a max-in-flight limit of 10.'];
$response = $client->beta->messages->create(
maxTokens: 1024,
messages: $messages,
model: 'claude-sonnet-5',
tools: $tools,
betas: ['advisor-tool-2026-03-01'],
);
client = Anthropic::Client.new
tools = [
{
type: "advisor_20260301",
name: "advisor",
model: "claude-opus-5"
}
]
messages = [
{
role: "user",
content: "Build a concurrent worker pool in Go with graceful shutdown."
}
]
response = client.beta.messages.create(
model: "claude-sonnet-5",
max_tokens: 1024,
tools: tools,
messages: messages,
betas: ["advisor-tool-2026-03-01"]
)
# Append the full response content, including any advisor_tool_result blocks
messages << { role: "assistant", content: response.content }
# Continue the conversation
messages << { role: "user", content: "Now add a max-in-flight limit of 10." }
response = client.beta.messages.create(
model: "claude-sonnet-5",
max_tokens: 1024,
tools: tools,
messages: messages,
betas: ["advisor-tool-2026-03-01"]
)
메시지 히스토리에 advisor_tool_result 블록이 여전히 있어도 이후 턴의 tools에서 어드바이저 도구를 뺄 수 있어요. 요청은 받아들여지고 이전 블록은 보존돼요. 그 턴의 모델은 어드바이저를 호출할 수 없어요. 그 히스토리 블록이 받아들여지려면 여전히 advisor-tool-2026-03-01 베타 헤더를 보내야 해요.
참고 (Note) 어드바이저 도구에는 내장된 대화 수준 한도가 없어요. 대화 전체에서 어드바이저 호출을 제한하려면 클라이언트 측에서 세세요. 한도에 도달하면
tools배열에서 어드바이저 도구를 제거하세요. 메시지 히스토리에서advisor_tool_result블록을 제거할 필요는 없어요.
일시 중지된 턴 재개하기 (Resuming a paused turn)
응답이 어드바이저 호출이 아직 보류된 상태에서 stop_reason: "pause_turn"으로 끝날 수 있어요. 그때 응답에는 어드바이저의 server_tool_use 블록이 그에 대한 advisor_tool_result 없이 포함돼요. 재개하려면 그 어시스턴트 메시지를 server_tool_use 블록을 유지한 채 내용 변경 없이 messages에 추가하고, 같은 어드바이저 도구와 베타 헤더로 요청을 다시 보내세요. user 메시지나 tool_result 블록을 추가할 필요는 없어요. API가 보류된 어드바이저 호출을 실행하고 새 응답에서 실행자의 턴을 계속해요. 재개된 턴은 다시 일시 중지될 수 있어요. 그러면 같은 단계를 반복하세요. 재개 요청에서 어드바이저 도구를 생략하면 400 invalid_request_error가 반환돼요. 보류된 server_tool_use 블록이 실행할 도구 정의가 없기 때문이에요. 호출이 보류 중일 때는 항상 도구를 포함하세요. 대신 같은 턴에 실행자가 여러분의 도구 중 하나를 호출했다면, 어드바이저 호출이 보류 중인 상태에서 응답은 stop_reason: "tool_use"로 끝나요. tool_result 블록을 평소처럼 보내고, 보류된 어드바이저 호출은 그 다음 요청의 시작에서 실행돼요. 한 턴에서 서버 도구와 클라이언트 도구 섞기를 참고하세요.
적게 호출하는 실행자를 위한 대화 중 넛지 (Mid-conversation nudge for under-calling executors)
Haiku 실행자가 첫 어시스턴트 턴에서 어드바이저를 호출하지 않았다면, 두 번째 어시스턴트 턴 전에 짧은 알림을 추가 user 메시지로 붙여보세요. Anthropic 내부 행동 평가에서 이는 Haiku 실행자에서 작업 통과율을 약 7퍼센트포인트 올렸어요. Sonnet 실행자에서는 평문 넛지가 Anthropic 테스트에서 측정 가능한 효과가 없었어요. 뒤따르는 호출 타이밍 고려 사항은 특히 Sonnet에 관련돼요. Opus 실행자에는 넛지를 적용하지 마세요. Opus에서는 통과율을 약간 낮췄어요.
기본 NUDGE_TURN인 2로, 알림은 보통 모델이 작업에 방향을 잡은 후 접근 방식을 정하기 전에 도착해요.
NUDGE_TURN = 2 # inject before this assistant turn if no advisor call yet NUDGE_TEXT = ( "You have not consulted the advisor yet. If the task has a non-obvious " "design decision or a failure mode you haven't ruled out, call advisor " "now before committing to an approach." ) MAX_TURNS = 10 # agent loop cap
def run_your_tools(content): # Replace with your tool dispatch. Returns one tool_result block per tool_use block. return [ { "type": "tool_result", "tool_use_id": block.id, "content": "Replace with your tool output.", } for block in content if block.type == "tool_use" ]
tools = [ {"type": "advisor_20260301", "name": "advisor", "model": "claude-opus-5"}, # ... your other tools ] task = "Build a concurrent worker pool in Go with graceful shutdown." messages = [{"role": "user", "content": task}] advisor_called = False
for turn in range(1, MAX_TURNS + 1): response = client.beta.messages.create( model="claude-haiku-4-5", max_tokens=4096, betas=["advisor-tool-2026-03-01"], tools=tools, messages=messages, ) messages.append({"role": "assistant", "content": response.content}) advisor_called = advisor_called or any( block.type == "server_tool_use" and block.name == "advisor" for block in response.content ) if response.stop_reason == "end_turn": break if response.stop_reason == "pause_turn": continue # server tool pending; re-send to let the API complete it
results = run_your_tools(response.content) # list of tool_result blocks
if results:
messages.append({"role": "user", "content": results})
# Skip this if your system prompt already tells the model to call sparingly.
if turn == NUDGE_TURN - 1 and not advisor_called:
messages.append({"role": "user", "content": NUDGE_TEXT})
```typescript TypeScript
const client = new Anthropic();
const NUDGE_TURN = 2; // inject before this assistant turn if no advisor call yet
const NUDGE_TEXT =
"You have not consulted the advisor yet. If the task has a non-obvious " +
"design decision or a failure mode you haven't ruled out, call advisor " +
"now before committing to an approach.";
const MAX_TURNS = 10; // agent loop cap
function runYourTools(
content: Anthropic.Beta.Messages.BetaContentBlock[]
): Anthropic.Beta.Messages.BetaToolResultBlockParam[] {
// Replace with your tool dispatch. Returns one tool_result block per tool_use block.
return content
.filter((block) => block.type === "tool_use")
.map((block) => ({
type: "tool_result" as const,
tool_use_id: block.id,
content: "Replace with your tool output."
}));
}
const tools: Anthropic.Beta.Messages.BetaToolUnion[] = [
{ type: "advisor_20260301", name: "advisor", model: "claude-opus-5" }
// ... your other tools
];
const task = "Build a concurrent worker pool in Go with graceful shutdown.";
const messages: Anthropic.Beta.Messages.BetaMessageParam[] = [{ role: "user", content: task }];
let advisorCalled = false;
for (let turn = 1; turn <= MAX_TURNS; turn++) {
const response = await client.beta.messages.create({
model: "claude-haiku-4-5",
max_tokens: 4096,
betas: ["advisor-tool-2026-03-01"],
tools,
messages
});
messages.push({ role: "assistant", content: response.content });
advisorCalled =
advisorCalled ||
response.content.some(
(block) => block.type === "server_tool_use" && block.name === "advisor"
);
if (response.stop_reason === "end_turn") {
break;
}
if (response.stop_reason === "pause_turn") {
continue; // server tool pending; re-send to let the API complete it
}
const results = runYourTools(response.content); // list of tool_result blocks
if (results.length > 0) {
messages.push({ role: "user", content: results });
}
// Skip this if your system prompt already tells the model to call sparingly.
if (turn === NUDGE_TURN - 1 && !advisorCalled) {
messages.push({ role: "user", content: NUDGE_TEXT });
}
}
using Anthropic.Models.Beta.Messages;
using Messages = Anthropic.Models.Messages;
var client = new AnthropicClient();
const int NudgeTurn = 2; // inject before this assistant turn if no advisor call yet
const string NudgeText =
"You have not consulted the advisor yet. If the task has a non-obvious "
+ "design decision or a failure mode you haven't ruled out, call advisor "
+ "now before committing to an approach.";
const int MaxTurns = 10; // agent loop cap
// Replace with your tool dispatch. Returns one tool_result block per tool_use block.
List<BetaContentBlockParam> RunYourTools(IReadOnlyList<BetaContentBlock> content)
{
List<BetaContentBlockParam> results = [];
foreach (var block in content)
{
if (block.TryPickToolUse(out var toolUse))
{
results.Add(new BetaToolResultBlockParam
{
ToolUseID = toolUse.ID,
Content = "Replace with your tool output."
});
}
}
return results;
}
var tools = new BetaToolUnion[]
{
new BetaAdvisorTool20260301 { Model = Messages::Model.ClaudeOpus5 }
// ... your other tools
};
var task = "Build a concurrent worker pool in Go with graceful shutdown.";
var messages = new List<BetaMessageParam> { new() { Role = Role.User, Content = task } };
var advisorCalled = false;
for (var turn = 1; turn <= MaxTurns; turn++)
{
var response = await client.Beta.Messages.Create(new MessageCreateParams
{
Model = Messages::Model.ClaudeHaiku4_5,
MaxTokens = 4096,
Tools = tools,
Messages = messages,
Betas = ["advisor-tool-2026-03-01"]
});
messages.Add(new BetaMessageParam
{
Role = Role.Assistant,
Content = response.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList()
});
advisorCalled =
advisorCalled
|| response.Content.Any(block =>
block.TryPickServerToolUse(out var serverToolUse)
&& serverToolUse.Name.Value() == Name.Advisor
);
if (response.StopReason == BetaStopReason.EndTurn)
{
break;
}
if (response.StopReason == BetaStopReason.PauseTurn)
{
continue; // server tool pending; re-send to let the API complete it
}
var results = RunYourTools(response.Content); // list of tool_result blocks
if (results.Count > 0)
{
messages.Add(new BetaMessageParam { Role = Role.User, Content = results });
}
// Skip this if your system prompt already tells the model to call sparingly.
if (turn == NudgeTurn - 1 && !advisorCalled)
{
messages.Add(new BetaMessageParam { Role = Role.User, Content = NudgeText });
}
}
const (
nudgeTurn = 2 // inject before this assistant turn if no advisor call yet
nudgeText = "You have not consulted the advisor yet. If the task has a non-obvious " +
"design decision or a failure mode you haven't ruled out, call advisor " +
"now before committing to an approach."
maxTurns = 10 // agent loop cap
)
// Replace with your tool dispatch. Returns one tool_result block per tool_use block.
func runYourTools(content []anthropic.BetaContentBlockUnion) []anthropic.BetaContentBlockParamUnion {
var results []anthropic.BetaContentBlockParamUnion
for _, block := range content {
if block.Type == "tool_use" {
results = append(results, anthropic.NewBetaToolResultBlock(block.ID, "Replace with your tool output.", false))
}
}
return results
}
func main() {
client := anthropic.NewClient()
tools := []anthropic.BetaToolUnionParam{
{OfAdvisorTool20260301: &anthropic.BetaAdvisorTool20260301Param{
Model: anthropic.ModelClaudeOpus5,
}},
// ... your other tools
}
task := "Build a concurrent worker pool in Go with graceful shutdown."
messages := []anthropic.BetaMessageParam{
anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock(task)),
}
advisorCalled := false
for turn := 1; turn <= maxTurns; turn++ {
response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
Model: anthropic.ModelClaudeHaiku4_5,
MaxTokens: 4096,
Tools: tools,
Messages: messages,
Betas: []anthropic.AnthropicBeta{
anthropic.AnthropicBetaAdvisorTool2026_03_01,
},
})
if err != nil {
log.Fatal(err)
}
messages = append(messages, response.ToParam())
for _, block := range response.Content {
if block.Type == "server_tool_use" && block.Name == "advisor" {
advisorCalled = true
}
}
if response.StopReason == anthropic.BetaStopReasonEndTurn {
break
}
if response.StopReason == anthropic.BetaStopReasonPauseTurn {
continue // server tool pending; re-send to let the API complete it
}
results := runYourTools(response.Content) // list of tool_result blocks
if len(results) > 0 {
messages = append(messages, anthropic.BetaMessageParam{
Role: anthropic.BetaMessageParamRoleUser,
Content: results,
})
}
// Skip this if your system prompt already tells the model to call sparingly.
if turn == nudgeTurn-1 && !advisorCalled {
messages = append(messages, anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock(nudgeText)))
}
}
}
import com.anthropic.models.beta.messages.BetaAdvisorTool20260301;
import com.anthropic.models.beta.messages.BetaContentBlock;
import com.anthropic.models.beta.messages.BetaContentBlockParam;
import com.anthropic.models.beta.messages.BetaMessage;
import com.anthropic.models.beta.messages.BetaMessageParam;
import com.anthropic.models.beta.messages.BetaServerToolUseBlock;
import com.anthropic.models.beta.messages.BetaStopReason;
import com.anthropic.models.beta.messages.BetaToolResultBlockParam;
import com.anthropic.models.beta.messages.BetaToolUnion;
import com.anthropic.models.beta.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;
static final int NUDGE_TURN = 2; // inject before this assistant turn if no advisor call yet
static final String NUDGE_TEXT =
"You have not consulted the advisor yet. If the task has a non-obvious "
+ "design decision or a failure mode you haven't ruled out, call advisor "
+ "now before committing to an approach.";
static final int MAX_TURNS = 10; // agent loop cap
// Replace with your tool dispatch. Returns one tool_result block per tool_use block.
List<BetaContentBlockParam> runYourTools(List<BetaContentBlock> content) {
List<BetaContentBlockParam> results = new ArrayList<>();
for (BetaContentBlock block : content) {
if (block.isToolUse()) {
results.add(BetaContentBlockParam.ofToolResult(
BetaToolResultBlockParam.builder()
.toolUseId(block.asToolUse().id())
.content("Replace with your tool output.")
.build()));
}
}
return results;
}
void main() {
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
List<BetaToolUnion> tools = List.of(
BetaToolUnion.ofAdvisorTool20260301(
BetaAdvisorTool20260301.builder().model(Model.CLAUDE_OPUS_5).build())
// ... your other tools
);
String task = "Build a concurrent worker pool in Go with graceful shutdown.";
List<BetaMessageParam> messages = new ArrayList<>();
messages.add(BetaMessageParam.builder()
.role(BetaMessageParam.Role.USER)
.content(task)
.build());
boolean advisorCalled = false;
for (int turn = 1; turn <= MAX_TURNS; turn++) {
BetaMessage response = client.beta().messages().create(MessageCreateParams.builder()
.model(Model.CLAUDE_HAIKU_4_5)
.maxTokens(4096L)
.tools(tools)
.messages(messages)
.addBeta("advisor-tool-2026-03-01")
.build());
messages.add(BetaMessageParam.builder()
.role(BetaMessageParam.Role.ASSISTANT)
.contentOfBetaContentBlockParams(
response.content().stream().map(BetaContentBlock::toParam).toList())
.build());
advisorCalled = advisorCalled
|| response.content().stream().anyMatch(block ->
block.isServerToolUse()
&& block.asServerToolUse().name().equals(BetaServerToolUseBlock.Name.ADVISOR));
BetaStopReason stopReason = response.stopReason().orElse(null);
if (BetaStopReason.END_TURN.equals(stopReason)) {
break;
}
if (BetaStopReason.PAUSE_TURN.equals(stopReason)) {
continue; // server tool pending; re-send to let the API complete it
}
List<BetaContentBlockParam> results = runYourTools(response.content()); // list of tool_result blocks
if (!results.isEmpty()) {
messages.add(BetaMessageParam.builder()
.role(BetaMessageParam.Role.USER)
.contentOfBetaContentBlockParams(results)
.build());
}
// Skip this if your system prompt already tells the model to call sparingly.
if (turn == NUDGE_TURN - 1 && !advisorCalled) {
messages.add(BetaMessageParam.builder()
.role(BetaMessageParam.Role.USER)
.content(NUDGE_TEXT)
.build());
}
}
}
$client = new Client();
const NUDGE_TURN = 2; // inject before this assistant turn if no advisor call yet
const NUDGE_TEXT = "You have not consulted the advisor yet. If the task has a non-obvious "
. "design decision or a failure mode you haven't ruled out, call advisor "
. "now before committing to an approach.";
const MAX_TURNS = 10; // agent loop cap
// Replace with your tool dispatch. Returns one tool_result block per tool_use block.
function runYourTools(array $content): array
{
$results = [];
foreach ($content as $block) {
if ($block->type === 'tool_use') {
$results[] = [
'type' => 'tool_result',
'tool_use_id' => $block->id,
'content' => 'Replace with your tool output.',
];
}
}
return $results;
}
$tools = [
['type' => 'advisor_20260301', 'name' => 'advisor', 'model' => 'claude-opus-5'],
// ... your other tools
];
$task = 'Build a concurrent worker pool in Go with graceful shutdown.';
$messages = [['role' => 'user', 'content' => $task]];
$advisorCalled = false;
for ($turn = 1; $turn <= MAX_TURNS; $turn++) {
$response = $client->beta->messages->create(
maxTokens: 4096,
messages: $messages,
model: 'claude-haiku-4-5',
tools: $tools,
betas: ['advisor-tool-2026-03-01'],
);
$messages[] = ['role' => 'assistant', 'content' => $response->content];
foreach ($response->content as $block) {
if ($block->type === 'server_tool_use' && $block->name === 'advisor') {
$advisorCalled = true;
}
}
if ($response->stopReason === 'end_turn') {
break;
}
if ($response->stopReason === 'pause_turn') {
continue; // server tool pending; re-send to let the API complete it
}
$results = runYourTools($response->content); // list of tool_result blocks
if ($results !== []) {
$messages[] = ['role' => 'user', 'content' => $results];
}
// Skip this if your system prompt already tells the model to call sparingly.
if ($turn === NUDGE_TURN - 1 && !$advisorCalled) {
$messages[] = ['role' => 'user', 'content' => NUDGE_TEXT];
}
}
client = Anthropic::Client.new
NUDGE_TURN = 2 # inject before this assistant turn if no advisor call yet
NUDGE_TEXT =
"You have not consulted the advisor yet. If the task has a non-obvious " \
"design decision or a failure mode you haven't ruled out, call advisor " \
"now before committing to an approach."
MAX_TURNS = 10 # agent loop cap
# Replace with your tool dispatch. Returns one tool_result block per tool_use block.
def run_your_tools(content)
content.filter_map do |block|
next unless block.type == :tool_use
{ type: "tool_result", tool_use_id: block.id, content: "Replace with your tool output." }
end
end
tools = [
{ type: "advisor_20260301", name: "advisor", model: "claude-opus-5" }
# ... your other tools
]
task = "Build a concurrent worker pool in Go with graceful shutdown."
messages = [{ role: "user", content: task }]
advisor_called = false
(1..MAX_TURNS).each do |turn|
response = client.beta.messages.create(
model: "claude-haiku-4-5",
max_tokens: 4096,
tools: tools,
messages: messages,
betas: ["advisor-tool-2026-03-01"]
)
messages << { role: "assistant", content: response.content }
advisor_called ||= response.content.any? do |block|
block.type == :server_tool_use && block.name == :advisor
end
break if response.stop_reason == :end_turn
next if response.stop_reason == :pause_turn # server tool pending; re-send to let the API complete it
results = run_your_tools(response.content) # list of tool_result blocks
messages << { role: "user", content: results } unless results.empty?
# Skip this if your system prompt already tells the model to call sparingly.
messages << { role: "user", content: NUDGE_TEXT } if turn == NUDGE_TURN - 1 && !advisor_called
end
넛지를 같은 메시지의 형제 블록이 아니라 별도의 user 메시지로 도구 결과 뒤에 추가하세요. 연속된 user 메시지가 유효해요. Anthropic의 Haiku와 Sonnet 실행자 테스트에서 형제 블록과 동등하게 동작했어요. 별도 메시지 형태는 또한 알림이 도구 출력과 명확히 구별되게 해줘요.
트레이드오프: 넛지는 호출률을 높여서, 사소하게 단순한 작업을 불필요한 상담으로 몰아넣을 수 있어요. 워크로드가 단순 작업과 복잡 작업을 섞는다면 NUDGE_TURN을 3으로 올려 두 턴 작업이 넛지 발동 전에 완료되게 하거나, 이미 계산하는 작업-복잡성 신호에 넛지를 게이트하세요. 시스템 프롬프트에 이미 절제 언어("진정한 불확실성을 위해 어드바이저를 아껴라")가 있다면 두 지침이 충돌하므로 넛지를 완전히 생략하세요.
평문 넛지는 Haiku와 Sonnet 실행자에서 매우 두드러져요. Anthropic 테스트에서 넛지된 시도의 74%(Sonnet)98%(Haiku)가 턴 2에서 즉시 어드바이저를 호출했어요. 그것이 실행자가 문제를 읽거나 컨텍스트를 모으기 전에 닿으면 결과적인 어드바이저 호출은 저-컨텍스트가 되고 더 잘 타이밍된 이후의 호출을 밀어낼 수 있어요. 넛지를 추가하기 전에 실행자의 기준 첫 호출 턴을 측정하세요. 실행자가 이미 어드바이저를 안정적으로 호출하고 첫 호출이 보통 턴 N에 도달한다면 4퍼센트포인트의 작업 성능 하락과 상관관계가 있었어요. 기준 호출률이 86%인 브라우즈 워크로드에서는 같은 넛지가 작업 성능 비용 없이 참여를 높였어요.NUDGE_TURN을 N보다 크게 설정하세요. Anthropic 테스트에서 기준 첫 호출이 턴 7 이후인 워크로드에 턴-2 넛지를 한 것은 3
넛지 대신 특정 요청에 상담을 강제하려면 tool_choice를 {"type": "tool", "name": "advisor"}로 설정하세요. 도구 사용 강제하기의 제약이 적용돼요. 강제 도구 사용은 수동 확장 사고(thinking: {type: "enabled"})와 결합할 수 없어요. 둘 다 활성화하면 API가 400 invalid_request_error를 반환해요. 적응형 사고는 강제 도구 사용을 지원해요. Claude Fable 5.1과 Claude Mythos 5.1 실행자는 tool_choice 타입 tool과 any를 거부하므로 그 모델들에서는 프롬프트 넛지를 사용하세요.
스트리밍 (Streaming)
어드바이저 하위 추론은 스트리밍하지 않아요. 어드바이저가 실행되는 동안 실행자의 스트림이 일시 중지되고, 그 후 전체 결과가 단일 이벤트로 도착해요.
name: "advisor"를 가진 server_tool_use 블록이 어드바이저 호출이 시작됨을 신호해요. 일시 중지는 그 블록이 닫힐 때(content_block_stop) 시작돼요. 일시 중지 동안 스트림은 표준 SSE ping 키프앨리브(약 30초마다 발생) 외에는 조용해요. 짧은 어드바이저 호출은 ping을 보여주지 않을 수 있어요.
어드바이저가 끝나면 advisor_tool_result가 단일 content_block_start 이벤트로 완전히 도착해요 (델타 없음). 그러면 실행자 출력이 다시 스트리밍돼요.
업데이트된 usage.iterations 배열(어드바이저의 토큰 수를 반영)을 가진 message_delta 이벤트가 뒤따라요.
사용과 청구 (Usage and billing)
어드바이저 호출은 어드바이저 모델의 요금으로 청구되는 별도의 하위 추론으로 실행돼요. 사용량은 usage.iterations[] 배열에 보고돼요:
{
"usage": {
"input_tokens": 1760,
"cache_read_input_tokens": 412,
"cache_creation_input_tokens": 0,
"output_tokens": 531,
"iterations": [
{
"type": "message",
"input_tokens": 412,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0,
"output_tokens": 89
},
{
"type": "advisor_message",
"model": "claude-opus-5",
"input_tokens": 823,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0,
"output_tokens": 1612
},
{
"type": "message",
"input_tokens": 1348,
"cache_read_input_tokens": 412,
"cache_creation_input_tokens": 0,
"output_tokens": 442
}
]
}
}
최상위 usage 필드는 실행자 토큰만 반영해요. 어드바이저 토큰은 다른 요금으로 청구되므로 최상위 합계에 합산되지 않아요. type: "advisor_message"인 iterations는 어드바이저 모델 요금으로, type: "message"인 iterations는 실행자 모델 요금으로 청구돼요.
모든 최상위 usage 필드는 input_tokens, output_tokens, cache_read_input_tokens를 포함해 모든 실행자 iteration에 걸친 해당 필드의 합이에요. 각 실행자 iteration은 커지는 대화를 다시 보내므로 이후 iteration의 입력에는 이전 iteration의 출력이 포함돼요. 따라서 합산된 input_tokens는 어떤 단일 프롬프트의 크기보다 커요. 비용 추적 로직을 만들 때 전체 per-iteration 분해를 위해 usage.iterations를 사용하세요.
어드바이저 출력은 보통 텍스트 400700 토큰이거나, thinking을 포함하면 총 1,4001,800 토큰이에요. 비용 절감은 어드바이저가 여러분의 완전한 최종 출력을 생성하지 않는 데서 옵니다. 실행자가 그것을 더 낮은 요금으로 해요.
최상위 max_tokens는 실행자 출력에만 적용돼요. 어드바이저 하위 추론 토큰을 제한하지 않아요. 어드바이저 출력을 직접 제한하려면 도구 정의에 max_tokens 설정을 하세요. 어드바이저의 토큰도 실행자에게 적용된 어떤 작업 예산에서도 끌어오지 않아요.
Priority Tier는 각 모델에 독립적으로 적용돼요. 실행자 모델의 Priority Tier 약정은 어드바이저까지 확장되지 않아요. 어드바이저 호출은 조직이 어드바이저 모델에 대한 약정도 보유한 경우에만 Priority Tier에서 실행돼요.
어드바이저 프롬프트 캐싱 (Advisor prompt caching)
두 개의 독립적인 캐싱 계층이 있어요.
실행자 측 캐싱 (Executor-side caching)
advisor_tool_result 블록은 다른 콘텐츠 블록처럼 캐시 가능해요. 이후 턴에서 그 뒤에 놓인 cache_control 중단점이 히트해요. 실행자의 프롬프트는 클라이언트가 text를 받았든 encrypted_content를 받았든 항상 평문 지침을 포함하므로, 캐싱 동작은 두 결과 변형에서 동일해요.
어드바이저 측 캐싱 (Advisor-side caching)
도구 정의에 caching을 설정해 같은 대화 안의 호출들에 걸쳐 어드바이저 자체 트랜스크립트의 프롬프트 캐싱을 활성화해요:
const tools: Anthropic.Beta.Messages.BetaToolUnion[] = [
{
type: "advisor_20260301",
name: "advisor",
model: "claude-opus-5",
caching: { type: "ephemeral", ttl: "5m" }
}
];
using Anthropic.Models.Beta.Messages;
using Messages = Anthropic.Models.Messages;
var tools = new BetaToolUnion[]
{
new BetaAdvisorTool20260301
{
Model = Messages::Model.ClaudeOpus5,
Caching = new BetaCacheControlEphemeral { Ttl = Ttl.Ttl5m }
}
};
tools := []anthropic.BetaToolUnionParam{
{OfAdvisorTool20260301: &anthropic.BetaAdvisorTool20260301Param{
Model: anthropic.ModelClaudeOpus5,
Caching: anthropic.BetaCacheControlEphemeralParam{TTL: anthropic.BetaCacheControlEphemeralTTLTTL5m},
}},
}
import com.anthropic.models.beta.messages.BetaAdvisorTool20260301;
import com.anthropic.models.beta.messages.BetaCacheControlEphemeral;
import com.anthropic.models.beta.messages.BetaToolUnion;
import com.anthropic.models.messages.Model;
List<BetaToolUnion> tools = List.of(
BetaToolUnion.ofAdvisorTool20260301(BetaAdvisorTool20260301.builder()
.model(Model.CLAUDE_OPUS_5)
.caching(BetaCacheControlEphemeral.builder()
.ttl(BetaCacheControlEphemeral.Ttl.TTL_5M)
.build())
.build()));
$tools = [
[
'type' => 'advisor_20260301',
'name' => 'advisor',
'model' => 'claude-opus-5',
'caching' => ['type' => 'ephemeral', 'ttl' => '5m'],
],
];
tools = [
{
type: "advisor_20260301",
name: "advisor",
model: "claude-opus-5",
caching: { type: "ephemeral", ttl: "5m" }
}
]
N번째 호출의 어드바이저 프롬프트는 (N-1)번째 호출의 프롬프트에 세그먼트 하나가 더 추가된 것이므로, 프리픽스는 호출 간에 안정적이에요. caching을 활성화하면 각 어드바이저 호출이 캐시 항목을 쓰고, 다음 호출이 그 지점까지 읽고 델타만 지불해요. 두 번째 이후의 advisor_message iteration에서 cache_read_input_tokens가 0이 아니게 되는 것을 볼 수 있어요.
언제 켜야 하나: 어드바이저가 대화당 두 번 이하로 호출되면 캐시 쓰기가 읽기 절감보다 더 비싸요. 캐싱은 대략 어드바이저 호출 세 번에서 손익분기하고 그 이후로 개선돼요. 긴 에이전트 루프에는 켜고, 짧은 작업에는 꺼 두세요.
일관성 유지: caching을 한 번 설정하고 전체 대화 동안 그대로 두세요. 대화 중간에 끄고 켜는 것은 캐시 미스를 일으켜요.
경고 (Warning)
"all"이 아닌keep값의clear_thinking은 매 턴 어드바이저의 인용된 트랜스크립트를 바꿔서 어드바이저 측 캐시 미스를 일으켜요. 이것은 비용 저하일 뿐이에요. 지침 품질은 영향을 받지 않아요. 명시적clear_thinking구성 없이 확장 사고가 활성화되면 API는 기본적으로keep: {type: "thinking_turns", value: 1}을 사용해서 이 동작을 촉발해요 (이전 Opus/Sonnet 모델과 모든 Haiku 모델의 기본값이며, Opus 4.5+와 Sonnet 4.6+에서는 모든 턴을 유지하는 것이 기본이에요). 어드바이저 캐시 안정성을 보존하려면keep: "all"을 설정하세요.
다른 도구와 결합하기 (Combining with other tools)
어드바이저 도구는 다른 서버 측·클라이언트 측 도구와 함께 구성돼요. 모두 같은 tools 배열에 추가하세요:
const tools: Anthropic.Beta.Messages.BetaToolUnion[] = [
{
type: "web_search_20250305",
name: "web_search",
max_uses: 5
},
{
type: "advisor_20260301",
name: "advisor",
model: "claude-opus-5"
},
{
name: "run_bash",
description: "Run a bash command",
input_schema: {
type: "object",
properties: { command: { type: "string" } }
}
}
];
using System.Text.Json;
using Anthropic.Models.Beta.Messages;
using Messages = Anthropic.Models.Messages;
var tools = new BetaToolUnion[]
{
new BetaWebSearchTool20250305 { MaxUses = 5 },
new BetaAdvisorTool20260301 { Model = Messages::Model.ClaudeOpus5 },
new BetaTool
{
Name = "run_bash",
Description = "Run a bash command",
InputSchema = new()
{
Properties = new Dictionary<string, JsonElement>
{
["command"] = JsonSerializer.SerializeToElement(new { type = "string" })
}
}
}
};
tools := []anthropic.BetaToolUnionParam{
{OfWebSearchTool20250305: &anthropic.BetaWebSearchTool20250305Param{
MaxUses: anthropic.Int(5),
}},
{OfAdvisorTool20260301: &anthropic.BetaAdvisorTool20260301Param{
Model: anthropic.ModelClaudeOpus5,
}},
{OfTool: &anthropic.BetaToolParam{
Name: "run_bash",
Description: anthropic.String("Run a bash command"),
InputSchema: anthropic.BetaToolInputSchemaParam{
Properties: map[string]any{
"command": map[string]any{"type": "string"},
},
},
}},
}
import com.anthropic.core.JsonValue;
import com.anthropic.models.beta.messages.BetaAdvisorTool20260301;
import com.anthropic.models.beta.messages.BetaTool;
import com.anthropic.models.beta.messages.BetaToolUnion;
import com.anthropic.models.beta.messages.BetaWebSearchTool20250305;
import com.anthropic.models.messages.Model;
List<BetaToolUnion> tools = List.of(
BetaToolUnion.ofWebSearchTool20250305(BetaWebSearchTool20250305.builder()
.maxUses(5L)
.build()),
BetaToolUnion.ofAdvisorTool20260301(BetaAdvisorTool20260301.builder()
.model(Model.CLAUDE_OPUS_5)
.build()),
BetaToolUnion.ofBetaTool(BetaTool.builder()
.name("run_bash")
.description("Run a bash command")
.inputSchema(BetaTool.InputSchema.builder()
.properties(JsonValue.from(Map.of(
"command", Map.of("type", "string"))))
.build())
.build()));
$tools = [
[
'type' => 'web_search_20250305',
'name' => 'web_search',
'max_uses' => 5,
],
[
'type' => 'advisor_20260301',
'name' => 'advisor',
'model' => 'claude-opus-5',
],
[
'name' => 'run_bash',
'description' => 'Run a bash command',
'input_schema' => [
'type' => 'object',
'properties' => ['command' => ['type' => 'string']],
],
],
];
tools = [
{
type: "web_search_20250305",
name: "web_search",
max_uses: 5
},
{
type: "advisor_20260301",
name: "advisor",
model: "claude-opus-5"
},
{
name: "run_bash",
description: "Run a bash command",
input_schema: {
type: "object",
properties: { command: { type: "string" } }
}
}
]
실행자는 같은 턴에서 웹을 검색하고, 어드바이저를 호출하고, 커스텀 도구를 사용할 수 있어요. 어드바이저의 계획이 실행자가 다음에 어떤 도구를 집는지에 알려줄 수 있어요.
| 기능 | 상호작용 |
|---|---|
| 배치 처리 | 지원돼요. usage.iterations가 항목별로 보고돼요. |
| 토큰 카운팅 | 실행자의 첫 iteration 입력 토큰만 반환해요. 대략적인 어드바이저 추정을 위해 model을 어드바이저 모델로 설정하고 같은 메시지로 count_tokens를 호출하세요. |
| 컨텍스트 편집 | clear_tool_uses는 어드바이저 도구 블록과 완전히 호환되지 않아요. clear_thinking에 대해서는 앞선 캐싱 경고를 참고하세요. |
pause_turn |
매달린 어드바이저 호출은 같은 턴에서 여러분의 결과를 기다리는 클라이언트 tool_use 블록이 없을 때 stop_reason: "pause_turn"과 결과 없는 server_tool_use 블록으로 응답을 끝내요. 어드바이저는 재개 시 실행돼요. 그 턴에 실행자가 여러분의 도구 중 하나도 호출했다면 응답은 대신 stop_reason: "tool_use"로 끝나고, 보류된 어드바이저 호출은 여러분이 tool_result 블록을 보낸 후 다음 요청의 시작에서 실행돼요. 일시 중지된 턴 재개하기, 한 턴에서 서버 도구와 클라이언트 도구 섞기, 서버 도구 참고. |
모범 사례 (Best practices)
코딩 및 에이전트 작업 프롬프팅 (Prompting for coding and agent tasks)
어드바이저 도구에는 복잡한 작업의 시작과 어려움에 부딪힐 때 호출하도록 실행자를 살짝 밀어주는 내장 설명이 들어 있어요. 연구 작업에는 보통 추가 프롬프팅이 필요 없어요.
코딩 및 에이전트 작업에서 어드바이저는 총 도구 호출과 대화 길이를 줄일 때 비슷한 비용으로 더 높은 지능을 만들어요. 이 개선을 이끄는 두 가지 타이밍이 있어요:
- 트랜스크립트에 약간의 탐색적 읽기가 들어간 후의 이른 첫 어드바이저 호출.
- 어려운 작업의 경우 파일 쓰기와 테스트 출력이 트랜스크립트에 들어간 후의 마지막 어드바이저 호출.
에이전트가 다른 플래너류 도구(예: 할 일 목록 도구)를 노출한다면, 어드바이저의 계획이 그들로 흘러들어가도록 그 도구들 앞에서 모델에 어드바이저를 호출하라고 프롬프트 하세요. 제안된 시스템 프롬프트가 이른 호출 패턴을 강화해요. 에이전트가 노출하는 어떤 플래너 도구를 가리키는 나만의 funnel-in 문장을 추가하세요.
코딩 작업용 제안된 시스템 프롬프트 (Suggested system prompt for coding tasks)
시스템 프롬프트 조향 없이 실행자는 일부 도메인, 특히 코딩 작업에서 어드바이저를 적게 호출하는 경향이 있어요. 일관된 어드바이저 타이밍과 작업당 약 2~3회 호출을 원하는 코딩 작업에서는, 어드바이저를 언급하는 다른 어떤 문장들보다 앞서 실행자 시스템 프롬프트에 다음 블록들을 앞에 붙이세요.
타이밍 지침:
You have access to an `advisor` tool backed by a stronger reviewer model. It takes NO parameters — when you call advisor(), your entire conversation history is automatically forwarded. They see the task, every tool call you've made, every result you've seen.
Call advisor BEFORE substantive work — before writing, before committing to an interpretation, before building on an assumption. If the task requires orientation first (finding files, fetching a source, seeing what's there), do that, then call advisor. Orientation is not substantive work. Writing, editing, and declaring an answer are.
Also call advisor:
- When you believe the task is complete. BEFORE this call, make your deliverable durable: write the file, save the result, commit the change. The advisor call takes time; if the session ends during it, a durable result persists and an unwritten one doesn't.
- When stuck — errors recurring, approach not converging, results that don't fit.
- When considering a change of approach.
On tasks longer than a few steps, call advisor at least once before committing to an approach and once before declaring done. On short reactive tasks where the next action is dictated by tool output you just read, you don't need to keep calling — the advisor adds most of its value on the first call, before the approach crystallizes.
실행자가 지침을 대하는 방법 (타이밍 블록 바로 뒤에 배치):
Give the advice serious weight. If you follow a step and it fails empirically, or you have primary-source evidence that contradicts a specific claim (the file says X, the paper states Y), adapt. A passing self-test is not evidence the advice is wrong — it's evidence your test doesn't check what the advice is checking.
If you've already retrieved data pointing one way and the advisor points another: don't silently switch. Surface the conflict in one more advisor call — "I found X, you suggest Y, which constraint breaks the tie?" The advisor saw your evidence but may have underweighted it; a reconcile call is cheaper than committing to the wrong branch.
코딩 워크로드의 Haiku용 대체 시스템 프롬프트 (Alternative system prompt for Haiku on coding workloads)
Claude Haiku 4.5는 기본 어드바이저 지침을 보수적으로 적용해요. 이는 연구 및 조회 워크로드에서 호출률을 적절히 낮게 유지하지만, 이른 어드바이저 상담이 안정적으로 비용을 되갚는 코딩 워크로드에서는 품질을 포기해요. 내부 코딩 벤치마크에서 다음 블록과 가까운 변형(Hard rule의 읽기 전용 제외는 측정 후 추가)이 기본값 대비 Haiku 통과율을 약 7.5퍼센트포인트 올렸어요.
Haiku 실행자가 코딩 또는 쓰기 작업 워크로드를 주로 돌릴 때 앞선 타이밍·지침 블록 대신 이 블록을 사용하세요:
Consult a stronger reviewer who sees your full conversation transcript.
No parameters. When you call advisor(), your entire history -- task, every tool call and result, your reasoning -- is automatically forwarded. The advisor sees exactly what you've done.
Call advisor BEFORE substantive work -- before writing, before committing to an interpretation, before building on an assumption. If the task requires orientation first (finding files, fetching a source, seeing what's there), do that, then call advisor. Orientation is not substantive work. Writing, editing, and declaring an answer are.
Also call advisor:
- When you believe the task is complete. BEFORE this call, make your deliverable durable: write the file, save the result, commit the change. The advisor call takes time; if the session ends during it, a durable result persists and an unwritten one doesn't.
- When stuck -- errors recurring, approach not converging, results that don't fit.
- When considering a change of approach.
On tasks longer than a few steps, call advisor at least once before committing to an approach and once before declaring done. On short reactive tasks where the next action is dictated by tool output you just read, you don't need to keep calling -- the advisor adds most of its value on the first call, before the approach crystallizes.
Give the advice serious weight. If you follow a step and it fails empirically, or you have primary-source evidence that contradicts a specific claim (the file says X, the paper states Y), adapt. A passing self-test is not evidence the advice is wrong -- it's evidence your test doesn't check what the advice is checking.
If you've already retrieved data pointing one way and the advisor points another: don't silently switch. Surface the conflict in one more advisor call -- "I found X, you suggest Y, which constraint breaks the tie?" The advisor saw your evidence but may have underweighted it; a reconcile call is cheaper than committing to the wrong branch.
Call advisor for design, architecture, and risk questions where you won't touch a file. If your response would be analysis or a recommendation with no other tool calls, call advisor first -- that judgment call is exactly where a second opinion is highest-value.
Hard rule: your first write_file, edit_file, or state-changing bash call on a task must be preceded by an advisor call in the same or an earlier turn. Read-only orientation commands (ls, cat, grep, find) are not state-changing. This is a checkpoint, not a difficulty judgment. It applies to one-line edits too.
주의 (Caveat): 내부 브라우즈-이해 벤치마크(n = 1,266)에서 이 블록과 가까운 변형이 기본값 대비 정확도 약 4퍼센트포인트의 비용이 들었어요. 워크로드가 코딩과 상당한 조회·검색을 섞는다면 제안된 블록을 유지하거나, 이미 계산하는 워크로드-타입 신호에 전환을 게이트하세요.
Opus 실행자에서 어드바이저 호출 늘리기 (Increasing advisor calls on Opus executors)
Opus 실행자는 보통 추가 프롬프팅 없이 적절한 비율로 어드바이저를 호출해요. Opus 실행자가 워크로드에서 적게 호출한다면 시스템 프롬프트에 다음 체크포인트를 추가하세요:
Call advisor for design, architecture, and risk questions where you won't touch a file. If your response would be analysis or a recommendation with no other tool calls, call advisor first. That judgment call is exactly where a second opinion is highest-value. (This does not apply to simple factual lookups or arithmetic; those you answer directly.)
Hard rule: your first write_file, edit_file, or state-changing bash call on a task must be preceded by an advisor call in the same or an earlier turn. Read-only orientation commands (ls, cat, grep, find) are not state-changing. This is a checkpoint, not a difficulty judgment. It applies to one-line edits too.
주의 (Caveat): Anthropic 테스트에서 이 블록과 가까운 변형(Hard rule의 읽기 전용 제외는 측정 후 추가)은 적게 호출하는 작업의 통과율을 약 7~10퍼센트포인트 올렸지만, 첫 행동에 계획이 필요 없는 작업에서는 Opus가 과도하게 호출하게 했어요. 혼합 워크로드에서 순 효과는 대략 평평했어요. 상담이 도움이 되었을 작업에서 Opus가 어드바이저를 건너뛰는 것을 관찰한 경우에만 추가하세요. 기본값으로 추가하지 마세요.
어드바이저 출력 길이 줄이기 (Trimming advisor output length)
어드바이저 출력은 어드바이저의 가장 큰 비용 동인이고, 최상위 max_tokens는 그것을 제한하지 않아요. 어드바이저는 시스템 프롬프트와 user 메시지 모두를 실행자 작업에 관한 인용된 컨텍스트로 보므로, 어드바이저를 직접 다루는 지침은 3인칭 설명보다 훨씬 안정적으로 따라져요. Anthropic이 테스트한 가장 효과적인 배치는 user 메시지의 한 줄이에요:
(Advisor: please keep your guidance under 80 words — I need a focused starting point, not a comprehensive plan.)
이 줄은 요청을 보내기 전에 에이전트 프레임워크가 프로그래매틱하게 접두사로 붙일 수 있어요. 한계는 소프트 제약이에요. 어드바이저가 가끔 초과하므로 진짜 상한의 약 80%를 요청하세요.
참고 (Note) Anthropic 테스트에서 이 줄은 또한 실행자가 어드바이저를 참고하는 빈도를 높였지만, 순 효과는 여전히 더 낮은 총 비용이었어요 (더 많은 참고, 각각 더 짧음).
이 접근을 코딩 작업용 제안된 시스템 프롬프트의 타이밍 지침(또는 바꿔 넣었다면 대체 Haiku 블록)과 짝지어 가장 강한 비용-대-품질 트레이드오프를 얻으세요. 소프트 요청이 아닌 하드 한도가 필요하면 어드바이저 출력 제한하기를 참고하세요.
어드바이저 출력 제한하기 (Capping advisor output)
도구 정의에 max_tokens를 설정해 호출당 어드바이저 총 출력(thinking + 텍스트)을 제한해요:
const tools: Anthropic.Beta.Messages.BetaToolUnion[] = [
{
type: "advisor_20260301",
name: "advisor",
model: "claude-opus-5",
max_tokens: 2048
}
];
using Anthropic.Models.Beta.Messages;
using Messages = Anthropic.Models.Messages;
var tools = new BetaToolUnion[]
{
new BetaAdvisorTool20260301
{
Model = Messages::Model.ClaudeOpus5,
MaxTokens = 2048
}
};
tools := []anthropic.BetaToolUnionParam{
{OfAdvisorTool20260301: &anthropic.BetaAdvisorTool20260301Param{
Model: anthropic.ModelClaudeOpus5,
MaxTokens: anthropic.Int(2048),
}},
}
import com.anthropic.models.beta.messages.BetaAdvisorTool20260301;
import com.anthropic.models.beta.messages.BetaToolUnion;
import com.anthropic.models.messages.Model;
List<BetaToolUnion> tools = List.of(
BetaToolUnion.ofAdvisorTool20260301(BetaAdvisorTool20260301.builder()
.model(Model.CLAUDE_OPUS_5)
.maxTokens(2048L)
.build()));
$tools = [
[
'type' => 'advisor_20260301',
'name' => 'advisor',
'model' => 'claude-opus-5',
'max_tokens' => 2048,
],
];
tools = [
{
type: "advisor_20260301",
name: "advisor",
model: "claude-opus-5",
max_tokens: 2048
}
]
최소값은 1024예요. 어드바이저 모델 자체의 출력 한도보다 높게 max_tokens를 설정하면 400 오류가 반환돼요. 한도는 각 어드바이저 호출에 독립적으로 적용되며 같은 요청의 호출들 사이에 공유되지 않아요.
이것은 혼자서 하드 자르기(truncation)가 아니에요. 서버는 또한 어드바이저에게 남은 토큰 예산을 전달하므로 어드바이저가 응답을 맞춰 형성해요.
권장 시작점: max_tokens: 2048. Anthropic의 하드 추론 벤치마크 테스트(구성당 n = 40)에서 이는 한도를 설정하지 않은 것 대비 평균 어드바이저 출력을 약 7배 줄였고, 잘림은 거의 0, 감지 가능한 품질 저하도 없었어요. 1024의 최소값은 출력을 약 10배 줄였지만 호출의 약 10%를 잘랐어요. 이 표본 크기에서 모든 구성의 정확도 차이는 노이즈 범위 안이었어요. 자체 워크로드에서 검증하세요.
max_tokens |
평균 어드바이저 출력 토큰 | 잘린 호출 |
|---|---|---|
| 설정 안 함 | ~4,200~5,900 | 해당 없음 |
| 2048 | ~630~840 | ~0% |
| 1024 | ~370~480 | ~10% |
하드 추론 작업은 더 가벼운 워크로드에 대해 앞서 인용한 전형적인 1,400~1,800 토큰보다 현저히 긴 어드바이저 출력을 이끌어요. 이 표를 절감 비율 측정에 사용하지 말고, 어드바이저 출력의 보편적 기준선으로 사용하지 마세요.
어드바이저가 실제로 한도에 도달하면 어떤 어드바이저 모델을 쓰든 두 결과 변형 모두에서 결과 블록이 stop_reason: "max_tokens"를 담아요. stop_reason으로 잘린 지침을 감지하고 한도를 올릴지, 부분 지침으로 실행자가 진행하게 할지 결정하세요. API는 또한 지침 텍스트에 [Advisor output truncated at max_tokens=2048.](여러분의 한도 명명)을 추가해서 실행자가 자신의 컨텍스트에서 잘림을 보게 해요. 평문 advisor_result 어드바이저에서는 그 표시가 여러분의 클라이언트에도 보여요. 두 신호 모두 도구 정의에 max_tokens를 설정할 때만 나타나요.
{
"type": "advisor_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "advisor_redacted_result",
"encrypted_content": "EqQBCkYIBRgCIiQ3YTAwMjY1Mi1mZjM5LTQ1NGUtODgxNC1kNjNjNTk1ZWI3Y...",
"stop_reason": "max_tokens"
}
}
usage.iterations의 해당 advisor_message 항목에서 output_tokens를 확인해 각 호출이 한도에 얼마나 가까웠는지 보세요.
프롬프트 기반 접근과 비교해 max_tokens는 소프트 요청이 아닌 하드 상한이에요. 비용이나 지연에 대한 보장된 한도가 필요할 때 max_tokens를 사용하세요. 사고 중간에 끊기는 위험 없이 간결함 쪽으로 편향시키고 싶을 때는 프롬프트 기반 접근(또는 둘 다)을 사용하세요.
노력 설정과 짝짓기 (Pairing with effort settings)
코딩 작업에서 중간 노력(effort)의 Sonnet 실행자를 Opus 어드바이저와 짝지으면 기본 노력의 Sonnet과 비슷한 지능을 더 낮은 비용으로 얻어요. 최대 지능을 원하면 실행자를 기본 노력으로 유지하세요.
비용 통제 (Cost control)
- 대화 수준 예산을 위해 어드바이저 호출을 클라이언트 측에서 세세요. 한도에 도달하면
tools에서 어드바이저 도구를 제거하세요. 메시지 히스토리에서advisor_tool_result블록을 제거할 필요는 없어요 (다중 턴 대화의 참고 참고). - 어드바이저 호출이 세 번 이상 예상되는 대화에서만
caching을 활성화하세요.
모델 호환성 (Model compatibility)
실행자 모델(최상위 model 필드)과 어드바이저 모델(도구 정의 안의 model 필드)은 유효한 쌍을 이루어야 해요. 어드바이저는 Claude Sonnet 4.6 또는 더 유능한 모델이어야 하고, 실행자보다 적어도 같은 만큼 유능해야 해요. 같은 능력의 모델(예: Claude Opus 4.7과 Claude Opus 4.8)은 서로 어드바이스할 수 있어요.
| 실행자 모델 | 어드바이저 모델 |
|---|---|
| Claude Haiku 4.5 (claude-haiku-4-5) | Claude Mythos 5.1 (claude-mythos-5-1) Claude Fable 5.1 (claude-fable-5-1) Claude Mythos 5 (claude-mythos-5) Claude Fable 5 (claude-fable-5) Claude Opus 5 (claude-opus-5) Claude Opus 4.8 (claude-opus-4-8) Claude Opus 4.7 (claude-opus-4-7) Claude Opus 4.6 (claude-opus-4-6) Claude Sonnet 5 (claude-sonnet-5) Claude Sonnet 4.6 (claude-sonnet-4-6) |
| Claude Sonnet 4.6 (claude-sonnet-4-6) | Claude Mythos 5.1 (claude-mythos-5-1) Claude Fable 5.1 (claude-fable-5-1) Claude Mythos 5 (claude-mythos-5) Claude Fable 5 (claude-fable-5) Claude Opus 5 (claude-opus-5) Claude Opus 4.8 (claude-opus-4-8) Claude Opus 4.7 (claude-opus-4-7) Claude Opus 4.6 (claude-opus-4-6) Claude Sonnet 5 (claude-sonnet-5) Claude Sonnet 4.6 (claude-sonnet-4-6) |
| Claude Sonnet 5 (claude-sonnet-5) | Claude Mythos 5.1 (claude-mythos-5-1) Claude Fable 5.1 (claude-fable-5-1) Claude Mythos 5 (claude-mythos-5) Claude Fable 5 (claude-fable-5) Claude Opus 5 (claude-opus-5) Claude Opus 4.8 (claude-opus-4-8) Claude Opus 4.7 (claude-opus-4-7) Claude Sonnet 5 (claude-sonnet-5) |
| Claude Opus 4.6 (claude-opus-4-6) | Claude Mythos 5.1 (claude-mythos-5-1) Claude Fable 5.1 (claude-fable-5-1) Claude Mythos 5 (claude-mythos-5) Claude Fable 5 (claude-fable-5) Claude Opus 5 (claude-opus-5) Claude Opus 4.8 (claude-opus-4-8) Claude Opus 4.7 (claude-opus-4-7) Claude Opus 4.6 (claude-opus-4-6) Claude Sonnet 5 (claude-sonnet-5) |
| Claude Opus 4.7 (claude-opus-4-7) | Claude Mythos 5.1 (claude-mythos-5-1) Claude Fable 5.1 (claude-fable-5-1) Claude Mythos 5 (claude-mythos-5) Claude Fable 5 (claude-fable-5) Claude Opus 5 (claude-opus-5) Claude Opus 4.8 (claude-opus-4-8) Claude Opus 4.7 (claude-opus-4-7) |
| Claude Opus 4.8 (claude-opus-4-8) | Claude Mythos 5.1 (claude-mythos-5-1) Claude Fable 5.1 (claude-fable-5-1) Claude Mythos 5 (claude-mythos-5) Claude Fable 5 (claude-fable-5) Claude Opus 5 (claude-opus-5) Claude Opus 4.8 (claude-opus-4-8) Claude Opus 4.7 (claude-opus-4-7) |
| Claude Opus 5 (claude-opus-5) | Claude Mythos 5.1 (claude-mythos-5-1) Claude Fable 5.1 (claude-fable-5-1) Claude Mythos 5 (claude-mythos-5) Claude Fable 5 (claude-fable-5) Claude Opus 5 (claude-opus-5) |
| Claude Fable 5 (claude-fable-5) | Claude Mythos 5.1 (claude-mythos-5-1) Claude Fable 5.1 (claude-fable-5-1) Claude Mythos 5 (claude-mythos-5) Claude Fable 5 (claude-fable-5) Claude Opus 5 (claude-opus-5) |
| Claude Mythos 5 (claude-mythos-5) | Claude Mythos 5.1 (claude-mythos-5-1) Claude Fable 5.1 (claude-fable-5-1) Claude Mythos 5 (claude-mythos-5) Claude Fable 5 (claude-fable-5) Claude Opus 5 (claude-opus-5) |
| Claude Fable 5.1 (claude-fable-5-1) | Claude Mythos 5.1 (claude-mythos-5-1) Claude Fable 5.1 (claude-fable-5-1) |
| Claude Mythos 5.1 (claude-mythos-5-1) | Claude Mythos 5.1 (claude-mythos-5-1) Claude Fable 5.1 (claude-fable-5-1) |
유효하지 않은 쌍을 요청하면 API가 지원되지 않는 조합을 명명하는 400 invalid_request_error를 반환해요.
플랫폼 가용성 (Platform availability)
어드바이저 도구는 Claude API와 AWS의 Claude Platform에서 베타로 사용할 수 있어요. 현재 Amazon Bedrock, Google Cloud, Microsoft Foundry에서는 사용할 수 없어요.
Claude Managed Agents의 어드바이저 (Advisor on Claude Managed Agents)
Claude Managed Agents 세션도 어드바이저를 지원해요. 도구 정의가 아니라 에이전트의 일부로 구성해요. 에이전트의 멀티에이전트 명단에 {"type": "advisor", "model": ...} 항목을 추가하면 세션의 기본 스레드가 그 모델을 턴 중간에 참고할 수 있어요. 명단 항목은 max_uses, max_tokens, caching 옵션을 받지 않고, 지침은 응답의 advisor_tool_result 블록이 아니라 세션 이벤트 스트림의 스레드 이벤트로 전달돼요. 세션에 어드바이저 주기를 참고하세요.
더 알아보기 (Learn more)
- 메모리 도구 (Memory tool) — 클라이언트 측 메모리 디렉터리로 대화 간 정보를 저장·검색하기
- 서버 도구 (Server tools) — Anthropic 실행 도구 다루기: server_tool_use 블록, pause_turn 연속, 도메인 필터링
- 도구 레퍼런스 (Tool reference) — Anthropic 제공 도구 디렉터리와 선택적 도구 정의 속성
- 노력 (Effort) — effort 파라미터로 Claude가 응답에 쓰는 토큰 수를 제어해 응답 철저함과 토큰 효율 사이에서 절충하기