Haijun Platform Docs
ID

Agents are good at producing things that

look

done. Ask one for a cited research brief and you'll get a tidy document with footnotes. Look closer and there's usually room to improve: a topic gets thin coverage, a quote drifts from the source, a citation leans on a press release instead of the original filing. Catching those takes a manual review loop: you read the output, spot what's off, and prompt again. And most of what you say in those rounds is feedback you could have written down before the agent started.

[Outcomes](/docs/en/managed-agents/define-outcomes.html in Haijun Managed Agents gives the session a second agent whose only job is to check. You write a rubric that spells out what "done" looks like and how to verify it, and the platform provisions a grader in its own context window. The grader can't see the writer's reasoning and has no idea what shortcuts were taken. After each writer turn it rereads the artifact against the rubric and either passes it or hands back a per-criterion list of gaps. The writer revises and the loop runs again, up to a cap you set.

Write a rubric the grader can act on

Start a session with an Outcome and let the agent work toward it

Follow the grade-and-revise loop and read the grader's feedback

Recognize when Outcomes is the right tool

1. Set up the environment

ine-none">

env = client.beta.environments.create(

name="research-brief",

config={"type": "juglow_cloud", "networking": {"type": "unrestricted"}},

)

writer = client.beta.agents.create(

name="Research Analyst",

model=MODEL,

system="""You are a research analyst. You write one-page business briefs.

Cite every factual claim with an inline footnote [n]. End the brief with a Sources section in this exact format, one entry per line:

[n] "verbatim quote from the page, 25 words or fewer" - Title - URL

Only cite pages you actually fetched and read. The quote must be copied character-for-character from the page. Cite no more than 6 sources total. Pick the strongest; do not pad. Save the brief to /mnt/session/outputs/brief.md.""",

tools=[

{

"type": "agent_toolset_20260401",

"configs": [

{"name": "web_search"},

{"name": "web_fetch"},

{"name": "read"},

{"name": "write"},

],

}

],

betas=BETAS,

)

session = client.beta.sessions.create(

agent={"type": "agent", "id": writer.id, "version": writer.version},

environment_id=env.id,

title="Brief: EV fast-charging unit economics",

betas=BETAS,

)

print(f"Session {session.id}")

Session sesn_011CakRYQjc4NMXdRy4qKZy5 3. Write a rubric the grader can act on The define_outcome event hands the session two things: a description of the deliverable, which the writer reads, and a rubric, which the grader reads. After each writer turn the platform spins up a fresh grader with the same model and tools as the writer, gives it the rubric, and lets it inspect the artifact. The grader returns a per-criterion verdict, and if anything fails, the explanation goes straight back to the writer for the next revision.

v>

"max_iterations": 5,

},

],

)

BetaManagedAgentsSendSessionEvents(data=[BetaManagedAgentsUserDefineOutcomeEvent(id='sevt_011CakRYTKNkXJN7eh4kRs1r', description='Write a brief on the unit economics of public DC fast charging in the United States.\nThe brief should cover:\n 1. Capex range\n 2. Demand charges\n 3. Utilization breakeven\n 4. Subsidy programs\n 5. Named-operator economics\n 6. A contrarian or skeptical source\n 7. Hardware vs install cost split\n', max_iterations=5, outcome_id='outc_011CakRYTKNkJ83CBexcz13e', processed_at=datetime.datetime(2026, 5, 6, 1, 10, 30, 512206, tzinfo=TzInfo(0)), rubric=BetaManagedAgentsTextRubric(content='\nYou are reviewing a research brief at /mnt/session/outputs/brief.md against a coverage checklist and verifying its citations. The writer was told the seven topics to cover; this rubric defines what counts as sufficient coverage for each topic, and how to verify citations.\n\nCOVERAGE CHECKLIST. Each item has a specific area:\n 1. Capex range: a dollar range for installed cost per DC fast-charging stall or station.\n 2. Demand charges: quantified impact on opex (a $/kW figure or a % of operating cost).\n 3. Utilization breakeven: a breakeven or target utilization threshold (% or kWh/day).\n 4. Subsidy programs: NEVI or another public funding program, named.\n 5. Named operator: the GAAP net income or net loss from a specific public charging operator\'s most recent 10-K or 10-Q, and the citation for it must be the SEC filing itself (sec.gov), not a press release, earnings-call recap, or news article.\n 6. Contrarian source: at least one cited source whose thesis is that the economics are unfavorable or structurally challenged.\n 7. Cost split: a hardware vs soft-cost (install, permitting, grid) breakdown or ratio.\n\nCITATION CHECK. For every [n] entry in the Sources section:\n a. LIVE: Fetch the URL with web_fetch. Mark LIVE only if web_fetch returns the readable page directly. Mark DEAD if 404, parked, login-walled, paywalled, returns a bot-block/403, or renders only via JavaScript. Do NOT corroborate via mirrors, reposts, or search snippets; the cited URL itself must fetch.\n b. VERBATIM: Search the fetched page for the quoted string. Mark QUOTE_MATCH if the exact string appears (treat curly vs straight quotes as equivalent); NOT_FOUND otherwise.\n c. SUPPORTS CLAIM: Mark SUPPORTS_CLAIM if the quoted passage actually backs the claim it\'s cited on in the brief; UNSUPPORTED if it\'s tangential, contradicts the claim, or is just a general statement of fact.\n\nOUTPUT FORMAT: \n\nLine 1: Coverage N/7. Citations M/K verified.\n\nThen, for each failed item in the coverage checklist, create a new bullet, name the item and say what specific bar it failed in one sentence max per bullet. For example: "Item 3 Utilization breakeven - MISSING. ".\n\nThen, for each failed citation, create a new bullet with the format: "[n] domain - REASON. ". One sentence max per bullet. For example: "[3] evgo.com - DEAD. The URL returns a 403 error and appears to be behind a bot block. No mirrors or reposts; the cited URL itself must fetch."\n', type='text'), type='user.define_outcome')]) A few notes on the call above:

On this page
1. Set up the environment