Files
skills/skills/claude-api/shared/managed-agents-outcomes.md
Lance Martin 53048666b0 Update claude-api skill: Claude Fable 5.1 / Mythos 5.1, Managed Agents updates, cost-optimize (#1704)
* Update claude-api skill: Managed Agents self-hosted memory stores and web tool domain settings, cost-optimize subcommand, Admin API reference, ASCII-only text

Managed Agents: self-hosted sandboxes can now attach memory stores via the SDK worker (handle_item, ANTHROPIC_WORK_SECRET, sync options, troubleshooting); web_search/web_fetch accept allowed_domains/blocked_domains/user_location/max_content_tokens on the toolset configs entry and are not governed by environment networking; typed per-tool config unions; Console session viewer notes; packages caveat under limited networking; Claude Platform on AWS self-hosted worker auth.

New shared/cost-optimization.md backing a cost-optimize subcommand, and new shared/admin-api.md covering client.beta.organization in all SDKs and the CLI. Prompt caching gains TTL selection, automatic vs explicit breakpoint guidance, workspace isolation, and verification guidance. Sonnet 5 pricing is the permanent $2/$10 list price. Advisor pairing no longer excludes Claude Fable 5 for Managed Agents. Reviewer-only HTML comments are stripped from the published files.

All files are now plain ASCII in prose (em dashes, arrows, emoji callouts, and box-drawing replaced with ASCII equivalents), matching the source so future syncs diff cleanly.

No-Verification-Needed: documentation-only change to skill reference content

* Update claude-api skill: Claude Fable 5.1 / Mythos 5.1 catalog rows, Files and Skills APIs out of beta

Claude Fable 5.1 (claude-fable-5-1) and Claude Mythos 5.1 (claude-mythos-5-1) become the default Fable-tier models throughout the skill; Claude Fable 5 and Mythos 5 stay selectable by id with their own catalog rows. Feature-support lists that named Fable 5 now read Fable 5/5.1.

The Files API and Skills API are out of beta: examples use client.files.* / client.skills.* with no beta header, and the API-drift table points at the beta-to-GA migration docs.

No-Verification-Needed: documentation-only change to skill reference content

* Update claude-api skill: Claude Fable 5.1 / Mythos 5.1 migration section and API changes

Adds a "Migrating to Claude Fable 5.1 from Claude Fable 5" section to shared/model-migration.md: three breaking changes (forced tool_choice any/tool returns 400; thinking blocks are preserved only for the model that produced them or a newer one; and only in the conversation that produced them, so edited history replayed with thinking blocks is rejected), what carries over from Fable 5, the Opus 5 path, Mythos 5.1 notes, capability improvements, prompt-tunable behavioral shifts, and a migration checklist.

New API features documented: per-message effort (mid-conversation-output-config beta), turn-scoped mid-conversation system messages with clear_at, progress updates between tool calls via thinking.display "updates", thinking block_binding controls, and the 0.025x cache-read rate on Fable 5.1 with a max_tokens: 0 keep-alive that usually beats the 1-hour TTL.

Error catalog, prompt-caching, tool-use, platform-availability, cost-optimization, and prompt-audit are updated to match; SKILL.md routes migration and prompting questions to the new section.

No-Verification-Needed: documentation-only change to skill reference content

* Update claude-api skill: Claude Fable 5.1 launch-day hedges and migration-path table rows

Adds claude-fable-5 -> claude-fable-5-1 and claude-mythos-5 -> claude-mythos-5-1 rows to the migration-path and model-ID mapping tables (including the Bedrock IDs), and updates the refusal-fallback example to the 5.1 model id.

Hedges three claims until the launch docs confirm them: Task Budgets support on Claude Fable 5.1, whether Claude Mythos 5.1 shares the 0.025x cache-read rate, and the fallback-credit wording. The block_binding error row now says to send the controls beta header only where that beta is offered and to fall back to strip-and-retry elsewhere. Cross-references within the migration section point at the history-editing check directly.

No-Verification-Needed: documentation-only change to skill reference content
2026-09-01 11:30:38 -07:00

7.1 KiB

Managed Agents - Outcomes

An outcome elevates a session from conversation to work: you state what "done" looks like, and the harness runs an iterate -> grade -> revise loop until the artifact meets the rubric, hits max_iterations, or is interrupted. A separate grader (independent context window) scores each iteration against your rubric and feeds per-criterion gaps back to the agent.

The SDK sets the managed-agents-2026-04-01 beta header automatically on all client.beta.sessions.* calls; no additional header is required for outcomes.


The user.define_outcome event

Outcomes are not a field on sessions.create(). You create a normal session, then send a user.define_outcome event. The agent starts working on receipt - do not also send a user.message to kick it off.

You can collapse both calls into one by passing a single user.define_outcome in the session's initial_events array - same event, same rules, one round trip (see shared/managed-agents-core.md -> Seeding a session with initial_events). More than one user.define_outcome in that array, or one without a rubric, rejects the whole create with a 400.

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_MD},
            # or: "rubric": {"type": "file", "file_id": rubric.id}
            "max_iterations": 5,  # optional; default 3, max 20
        }
    ],
)
Field Type Notes
type "user.define_outcome"
description string The task. This is what the agent works toward - no separate user.message needed.
rubric {type: "text", content} | {type: "file", file_id} Required. Markdown with explicit, independently gradeable criteria. Upload once via client.beta.files.upload(...) (beta files-api-2025-04-14) to reuse across sessions.
max_iterations int Optional. Default 3, max 20.

The event is echoed back on the stream with a server-assigned outcome_id and processed_at.

Writing rubrics. Use explicit, gradeable criteria ("CSV has a numeric price column"), not vibes ("data looks good") - the grader scores each criterion independently, so vague criteria produce noisy loops. If you don't have a rubric, have Claude analyze a known-good artifact and turn that analysis into one.


Outcome-specific events

These appear on the standard event stream (sessions.events.stream / .list) alongside the usual agent.* / session.* events.

Event Payload highlights Meaning
span.outcome_evaluation_start outcome_id, iteration (0-indexed) Grader began scoring iteration N.
span.outcome_evaluation_ongoing outcome_id Heartbeat while the grader runs. Grader reasoning is opaque - you see that it's working, not what it's thinking.
span.outcome_evaluation_end outcome_evaluation_start_id, outcome_id, iteration, result, explanation, usage Grader finished one iteration. result drives what happens next (table below).

span.outcome_evaluation_end.result

result Next
satisfied Session -> idle. Terminal for this outcome.
needs_revision Agent starts another iteration.
max_iterations_reached No further grader cycles. Agent may run one final revision, then session -> idle.
failed Session -> idle. Rubric fundamentally doesn't match the task (e.g. description and rubric contradict).
interrupted Emitted whenever a user.interrupt arrives while an outcome is active - even if evaluation hadn't started. In that case outcome_evaluation_start_id is an empty string rather than an event ID, so don't use it as a lookup key without checking. (Except an interrupt sent while paused at the session budget, which is accepted and ignored - see shared/managed-agents-events.md § Reaching a session budget.)
{
  "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, ...",
  "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"
}

Checking status & retrieving deliverables

Status - either watch the stream for span.outcome_evaluation_end, or poll the session and read outcome_evaluations:

session = client.beta.sessions.retrieve(session.id)
for ev in session.outcome_evaluations:
    print(f"{ev.outcome_id}: {ev.result}")  # outc_01a...: satisfied

Deliverables - the agent writes to /mnt/session/outputs/. Once idle, fetch via the Files API with scope_id=session.id. This is the same session-outputs mechanism documented in shared/managed-agents-environments.md -> Session outputs (including the dual-beta-header requirement on files.list).


Interaction rules & pitfalls

  • One outcome at a time. Chain by sending the next user.define_outcome only after the previous one's terminal span.outcome_evaluation_end (satisfied / max_iterations_reached / failed / interrupted). The session retains history across chained outcomes.
  • Steering is allowed but optional. You may send user.message events mid-outcome to nudge direction, but the agent already knows to keep working until terminal - don't send "keep going" prompts. (Exception: a session paused at its budget (stop_reason: budget_reached) accepts only settle events - a steering user.message, or a chained user.define_outcome, is a 400 there; see shared/managed-agents-events.md § Reaching a session budget.)
  • user.interrupt pauses the current outcome - it marks result: "interrupted" and leaves the session idle, ready for a new outcome or conversational turn. (Exception: sent while paused at the session budget, the interrupt is accepted and ignored and the outcome stays active - see shared/managed-agents-events.md § Reaching a session budget.)
  • After terminal, the session is reusable - continue conversationally or define a new outcome.
  • Outcome != session-create field. Don't put outcome, rubric, or description on sessions.create() - outcomes are always sent as a user.define_outcome event.
  • Idle-break gate is unchanged. In your drain loop, keep using event.type === 'session.status_idle' && event.stop_reason?.type !== 'requires_action' - do not gate on span.outcome_evaluation_end alone (on needs_revision the session keeps running). See shared/managed-agents-client-patterns.md Pattern 5.

For the raw HTTP shapes and per-language SDK bindings beyond Python, WebFetch https://platform.claude.com/docs/en/managed-agents/define-outcomes.md (see shared/live-sources.md).