// my agent = a loop with two ways to stop
import { query } from "@anthropic-ai/claude-agent-sdk";
const goal = "find the 5 weirdest deep-sea creatures and write a fact file";
const tools = ["WebSearch", "Read", "Write"]; // allowed, not ordered!
const helpers = { "fact-checker": { description: "Double-checks every fact" } };
const workspace = { files, skills, memory }; // the agent's desk
for await (const msg of query({ // β» until answer is readyβ¦
prompt: goal,
options: {
allowedTools: tools, agents: helpers,
maxTurns: 10, // β¦or max turns reached
canUseTool: askMeFirst // human in the loop
}
})) workspace.memory.push(msg); // save each step into memory
Match the colours: every block on the Blocks tab is one piece of this real code.
THE REAL REQUEST β WHAT RUN ACTUALLY SENDS
// POST /v1/agents (then POST /v1/environments, POST /v1/sessions, user.message)
{
"name": "Deep-Sea Detective",
"model": "claude-sonnet-5",
"system": "You are a friendly kid-safe agent. Mission: find the 5 weirdest deep-sea creatures and write a fact file",
"tools": [{
"type": "agent_toolset_20260401",
"default_config": { "enabled": false },
"configs": [
{ "name": "web_search", "enabled": true,
"permission_policy": { "type": "always_ask" } },
{ "name": "read", "enabled": true, "permission_policy": { "type": "always_ask" } },
{ "name": "write", "enabled": true, "permission_policy": { "type": "always_ask" } }
]
}],
"skills": []
}
// then the outcome block kicks it off (no user.message needed):
{ "type": "user.define_outcome", "description": goal,
"rubric": { "type": "text", "content": "done looks likeβ¦" }, "max_iterations": 3 }
The exact JSON your blocks compile to β goal β system, toolbelt β configs, human in the loop β a check_with_me custom tool the agent must answer through you.