"Outcome"(결과)은 세션에 최종 결과물이 어떤 모습이어야 하는지, 그리고 그 품질을 어떻게 측정할지를 알려줍니다. 에이전트는 해당 목표를 향해 작업하며, 결과가 충족될 때까지 스스로 평가하고 반복합니다.
결과를 정의하면 하니스가 자동으로 grader(채점기)를 프로비저닝하여 루브릭에 따라 산출물을 평가합니다. 채점기는 메인 에이전트의 구현 선택에 영향을 받지 않도록 별도의 "context window"(컨텍스트 윈도우)를 사용합니다.
채점기는 어떤 기준이 통과했거나 실패했는지 요약하거나, 산출물이 루브릭을 충족함을 확인하는 설명을 반환합니다. 이 피드백은 다음 반복을 위해 에이전트에게 다시 전달됩니다.
"Rubric"(루브릭)은 기준별 채점 방식을 설명하는 마크다운 문서입니다. 루브릭은 필수입니다.
루브릭 예시:
# 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 이벤트를 전송합니다. 에이전트는 즉시 작업을 시작합니다. 추가적인 사용자 메시지 이벤트는 필요하지 않습니다.
# 세션 생성
session = client.beta.sessions.create(
agent=agent.id,
environment_id=environment.id,
title="Financial analysis on Costco",
)
# 결과 정의 — 에이전트가 수신 즉시 작업을 시작합니다
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},
# 또는: "rubric": {"type": "file", "file_id": rubric.id},
"max_iterations": 5, # optional; default 3, max 20
}
],
)결과 지향 세션의 진행 상황은 이벤트 스트림에 표시됩니다.
agent.* 이벤트(메시지 및 도구 사용 등)는 결과를 향한 진행 상황을 보여줍니다.span.outcome_evaluation_* 이벤트는 결과 지향 세션에서만 발생하며, 반복 루프 횟수와 채점기의 피드백 과정을 보여줍니다.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
}채점기가 하나의 반복 루프에 대한 평가를 시작하면 발생합니다. 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"
}채점기가 실행되는 동안 발생하는 하트비트입니다. 채점기의 내부 추론은 불투명합니다. 채점기가 작업 중이라는 것은 볼 수 있지만, 무엇을 생각하는지는 볼 수 없습니다.
{
"type": "span.outcome_evaluation_ongoing",
"id": "sevt_01ghi...",
"outcome_id": "outc_01a...",
"iteration": 0,
"processed_at": "2026-03-25T14:02:10Z"
}결과 평가 주기가 끝날 때 발생합니다. 채점기가 하나의 반복에 대한 평가를 마친 후, 또는 결과가 활성 상태인 동안 세션이 중단되었을 때입니다. 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를 통해 파일을 가져오세요.
# 이 세션에서 생성된 파일 목록 조회
# scope_id 필터링은 files 요청에 managed-agents 베타가 필요합니다
files = client.beta.files.list(scope_id=session.id, betas=["managed-agents-2026-04-01"])
for file in files:
print(file.id, file.filename)
# 파일 다운로드
if files.data:
content = client.files.download(files.data[0].id)
content.write_to_file("/tmp/output.txt")세션을 만들 때 사용자별 자격 증명을 등록합니다.
이벤트를 전송하고, 응답을 스트리밍하며, 실행 중에 세션을 중단하거나 방향을 전환합니다.
파일을 업로드하고 샌드박스에 마운트하여 읽고 처리합니다.
Was this page helpful?