결과(outcome)는 세션에 최종 결과물이 어떤 모습이어야 하는지와 그 품질을 어떻게 측정할지를 알려줍니다. 에이전트는 해당 목표를 향해 작업하며, 결과가 충족될 때까지 자체 평가하고 반복합니다.
결과를 정의하면 하네스가 자동으로 grader(채점기)를 프로비저닝하여 루브릭에 따라 아티팩트를 평가합니다. grader는 메인 에이전트의 구현 선택에 영향을 받지 않도록 별도의 컨텍스트 윈도우를 사용합니다.
grader는 어떤 기준이 통과하거나 실패했는지 요약하거나, 아티팩트가 루브릭을 충족한다는 것을 확인하는 설명을 반환합니다. 해당 피드백은 다음 반복을 위해 에이전트에게 다시 전달됩니다.
루브릭은 기준별 채점을 설명하는 마크다운 문서입니다. 루브릭은 필수입니다.
루브릭 예시:
# DCF Model Rubric
## Revenue Projections
- Uses historical revenue data from the last 5 fiscal years
- Projects revenue for at least 5 years forward
- Growth rate assumptions are explicitly stated and reasonable
## Cost Structure
- COGS and operating expenses are modeled separately
- Margins are consistent with historical trends or deviations are justified
## Discount Rate
- WACC is calculated with stated assumptions for cost of equity and cost of debt
- Beta, risk-free rate, and equity risk premium are sourced or justified
## Terminal Value
- Uses either perpetuity growth or exit multiple method (stated which)
- Terminal growth rate does not exceed long-term GDP growth
## Output Quality
- All figures are in a single .xlsx file with clearly labeled sheets
- Key assumptions are on a separate "Assumptions" sheet
- Sensitivity analysis on WACC and terminal growth rate is included루브릭을 user.define_outcome에 인라인 텍스트로 전달하거나(결과가 있는 세션 만들기 참조), 세션 간 재사용을 위해 Files API를 통해 업로드하세요.
import time
from pathlib import Path
from anthropic import Anthropic
client = Anthropic()
RUBRIC = """# DCF Model Rubric
## Revenue Projections
- Uses historical revenue data from the last 5 fiscal years
- Projects revenue for at least 5 years forward
## Output Quality
- All figures are in a single .xlsx file with clearly labeled sheets
"""
Path("/tmp/rubric.md").write_text(RUBRIC)
rubric = client.files.upload(file=Path("/tmp/rubric.md"))
print(f"Uploaded rubric: {rubric.id}")다음 예시는 기존 에이전트와 환경(둘 다 별도로 생성됨)에 대한 세션을 만든 다음, user.define_outcome 이벤트를 보냅니다. 에이전트는 즉시 작업을 시작합니다. 추가적인 사용자 메시지 이벤트는 필요하지 않습니다.
# Create a session
session = client.beta.sessions.create(
agent=agent.id,
environment_id=environment.id,
title="Financial analysis on Costco",
)
# Define the outcome — agent starts working on receipt
client.beta.sessions.events.send(
session_id=session.id,
events=[
{
"type": "user.define_outcome",
"description": "Build a DCF model for Costco in .xlsx",
"rubric": {"type": "text", "content": RUBRIC},
# or: "rubric": {"type": "file", "file_id": rubric.id},
"max_iterations": 5, # optional; default 3, max 20
}
],
)결과 지향 세션의 진행 상황은 이벤트 스트림에 표시됩니다.
agent.* 이벤트(메시지 및 도구 사용 등)는 결과를 향한 진행 상황을 보여줍니다.span.outcome_evaluation_* 이벤트는 결과 지향 세션에서만 발생하며, 반복 루프 횟수와 grader의 피드백 과정을 보여줍니다.user.message 이벤트를 보내 진행 중인 에이전트의 작업을 지시할 수도 있지만, 필수는 아닙니다. 에이전트는 성공하거나 반복 횟수를 소진할 때까지 스스로 반복하며 결과를 향해 작업합니다.user.interrupt 이벤트는 현재 결과에 대한 작업을 일시 중지하고 span.outcome_evaluation_end.result를 interrupted로 표시하여 새로운 결과를 시작할 수 있게 합니다.이것은 결과를 시작하기 위해 보내는 이벤트입니다. 수신 시 processed_at 타임스탬프와 outcome_id를 포함하여 다시 에코됩니다.
{
"type": "user.define_outcome",
"description": "Build a DCF model for Costco in .xlsx",
"rubric": { "type": "file", "file_id": "file_01..." },
"max_iterations": 5
}grader가 하나의 반복 루프에 대한 평가를 시작하면 발생합니다. iteration 필드는 0부터 시작하는 수정 카운터입니다. 0은 첫 번째 평가, 1은 첫 번째 수정 후의 재평가이며, 이후도 같은 방식입니다.
{
"type": "span.outcome_evaluation_start",
"id": "sevt_01def...",
"outcome_id": "outc_01a...",
"iteration": 0,
"processed_at": "2026-03-25T14:01:45Z"
}grader가 실행되는 동안 발생하는 하트비트입니다. grader의 내부 추론은 불투명합니다. 작동 중이라는 것은 볼 수 있지만, 무엇을 생각하고 있는지는 볼 수 없습니다.
{
"type": "span.outcome_evaluation_ongoing",
"id": "sevt_01ghi...",
"outcome_id": "outc_01a...",
"iteration": 0,
"processed_at": "2026-03-25T14:02:10Z"
}결과 평가 주기가 끝날 때 발생합니다. grader가 한 반복에 대한 평가를 완료한 후, 또는 결과가 활성 상태인 동안 세션이 중단될 때 발생합니다. result 필드는 다음에 일어날 일을 나타냅니다.
| Result | 다음 단계 |
|---|---|
satisfied | 세션이 idle로 전환됩니다. |
needs_revision | 에이전트가 새로운 반복 주기를 시작합니다. |
max_iterations_reached | 세션이 idle로 전환되기 전에 최종 확인 턴이 한 번 이어집니다. 추가 평가는 실행되지 않습니다. |
failed | 세션이 idle로 전환됩니다. 루브릭이 산출물에 적용되지 않는 경우(예: 설명과 루브릭이 서로 모순되는 경우) 반환됩니다. |
interrupted | 결과가 활성 상태인 동안 세션이 중단되면 평가가 아직 시작되지 않았더라도 발생합니다. 중단 전에 outcome_evaluation_start가 발생하지 않았다면 outcome_evaluation_start_id는 빈 문자열입니다. |
{
"type": "span.outcome_evaluation_end",
"id": "sevt_01jkl...",
"outcome_evaluation_start_id": "sevt_01def...",
"outcome_id": "outc_01a...",
"result": "satisfied",
"explanation": "All 12 criteria met: revenue projections use 5 years of historical data, WACC assumptions are stated, sensitivity table is included...",
"iteration": 0,
"usage": {
"input_tokens": 2400,
"output_tokens": 350,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 1800
},
"processed_at": "2026-03-25T14:03:00Z"
}이벤트 스트림에서 span.outcome_evaluation_end를 수신하거나, GET /v1/sessions/{session_id}를 폴링하여 outcome_evaluations[].result를 읽을 수 있습니다. 평가가 완료될 때까지 result는 pending, running 또는 evaluating을 보고합니다.
session = client.beta.sessions.retrieve(session.id)
for outcome in session.outcome_evaluations:
print(f"{outcome.outcome_id}: {outcome.result}")
# outc_01a...: satisfied에이전트는 샌드박스 내부의 /mnt/session/outputs/에 출력 파일을 작성합니다. 세션이 idle 상태가 되면 세션 범위로 지정된 Files API를 통해 가져오세요.
# List files produced by this session
# scope_id filtering requires the managed-agents beta on the files request
files = client.beta.files.list(scope_id=session.id, betas=["managed-agents-2026-04-01"])
for file in files:
print(file.id, file.filename)
# Download a file
if files.data:
content = client.files.download(files.data[0].id)
content.write_to_file("/tmp/output.txt")세션 생성 시 사용자별 자격 증명을 등록합니다.
이벤트를 보내고, 응답을 스트리밍하고, 실행 중에 세션을 중단하거나 방향을 변경합니다.
파일을 업로드하고 샌드박스에 마운트하여 읽고 처리합니다.
Was this page helpful?