The two objects the exam keeps circling back to — ClaudeAgentOptions (how you configure a run) and AgentDefinition (how you configure a subagent) — broken into exam-relevant pieces with a note on why each matters.
Domain 1 (Task tool for subagents) · Domain 2 (tool design & control)
Availability, auto-approval, and hard blocks are three different levers. Confusing them is a classic distractor: allowed_tools only decides what runs WITHOUT a prompt — it never widens or narrows what the model can see.
options = ClaudeAgentOptions(
tools=["Read", "Grep", "Glob", "Bash", "Skill"], # base availability (None = full default set)
allowed_tools=["Read", "Grep", "Glob"], # auto-approved, no prompt (does NOT restrict availability)
disallowed_tools=["Write", "Edit"], # hard-blocked; bare name = removed from context entirely
permission_mode="dontAsk", # default | acceptEdits | plan | dontAsk | bypassPermissions | auto
can_use_tool=custom_permission_handler, # fallback callback for prompt-bound decisions
)disallowed_tools wins over everything — a bare name removes the tool from context entirely. allowed_tools is about SKIPPING the prompt, not about capability. To let a coordinator spawn subagents you must keep Task available (see the Agents section).
disallowed_tools سب پر بھاری ہے — نام لکھتے ہی ٹول بالکل ہٹ جاتا ہے۔ allowed_tools کا مطلب صرف ’بغیر پوچھے چلے‘ ہے، طاقت کم زیادہ کرنا نہیں۔
async def custom_permission_handler(tool_name, input_data, context):
if tool_name == "Write" and input_data.get("file_path", "").startswith("/system/"):
return PermissionResultDeny(message="System writes blocked", interrupt=True)
return PermissionResultAllow(updated_input=input_data)Runs in code on every matching call, so it enforces a rule the prompt can only request. This is the same 'enforcement beats instruction' idea as hooks — reach for it when money, identity, or safety are on the line.
یہ ہر کال پر کوڈ میں چلتا ہے، اس لیے یہ اصول ’لاگو‘ کرتا ہے جو پرامپٹ صرف ’مانگ‘ سکتا ہے۔ پیسہ/شناخت/حفاظت ہو تو یہی استعمال کریں۔
Context management & caching
You can start from the Claude Code preset and only append to it. Excluding the dynamic sections keeps the prompt byte-identical between runs, which is what lets the prompt cache be reused.
system_prompt={
"type": "preset",
"preset": "claude_code",
"append": "Always cite file paths when referencing code.",
"exclude_dynamic_sections": True, # improves prompt-cache reuse across sessions
}exclude_dynamic_sections=True strips the parts that change every run (timestamps, env), so the cached prefix stays stable and hits the cache next time. Prefer append over rewriting the whole preset.
exclude_dynamic_sections=True وہ حصے ہٹا دیتا ہے جو ہر بار بدلتے ہیں، تاکہ کیش دوبارہ لگے۔ پورا پرامپٹ بدلنے کے بجائے append کریں۔
Domain 1 (orchestration) · Domain 2 (MCP configuration & scoping)
MCP servers are wired in here, and subagents can be declared up front so the coordinator can delegate to them by name. strict_mcp_config decides whether project/user MCP config is honored or ignored.
mcp_servers={
"calc": create_sdk_mcp_server(name="calc", version="1.0.0", tools=[]),
},
strict_mcp_config=False, # True = ignore project .mcp.json / user settings / connectorsstrict_mcp_config=True makes the run use ONLY the servers you pass here, ignoring .mcp.json and user connectors — the safe choice when you need a reproducible, locked-down tool surface.
strict_mcp_config=True صرف یہاں دیے گئے سرور استعمال کرتا ہے، .mcp.json اور یوزر کنیکٹرز کو نظر انداز — جب دہرایا جانے والا، محدود ماحول چاہیے۔
agents={
"code-reviewer": AgentDefinition(
description="Reviews code changes for style and bugs",
prompt="You are a meticulous code reviewer.",
),
}Subagents get isolated context — they do NOT inherit the coordinator's history. The description is how the coordinator decides WHEN to pick this subagent; the prompt is its whole world. See the full AgentDefinition below.
ہر سب ایجنٹ کا سیاق الگ ہوتا ہے — بڑے ایجنٹ کی گفتگو وراثت میں نہیں ملتی۔ description سے چناؤ ہوتا ہے، prompt ہی اُس کی پوری دنیا ہے۔
Model selection & reasoning effort
Pick the model, a fallback for when it is unavailable, a reasoning effort level, and an explicit thinking budget. Higher effort/thinking buys deeper reasoning at the cost of latency and tokens.
model="claude-sonnet-4-6",
fallback_model="claude-sonnet-4-5-20250929",
effort="high", # low | medium | high | xhigh | max
thinking={"type": "enabled", "budget_tokens": 20000, "display": "summarized"}fallback_model is your reliability net if the primary is unavailable. effort and thinking.budget_tokens are the two knobs that trade latency/cost for reasoning depth — turn them up only when the task actually needs it.
fallback_model بھروسے کا جال ہے جب اصل ماڈل دستیاب نہ ہو۔ effort اور thinking بجٹ گہری سوچ بمقابلہ وقت/لاگت کا سودا ہیں — ضرورت پر ہی بڑھائیں۔
Reliability & cost control (runaway-loop guardrails)
Hard ceilings that stop a runaway loop before it burns the budget: a turn cap, a dollar cap, and an API-side token budget.
max_turns=30,
max_budget_usd=2.50,
task_budget={"total": 50000} # API-side token budget (beta header sent automatically)These are deterministic guardrails, not suggestions. When an exam scenario describes an agent looping forever or overspending, the fix is a hard cap here — not a prompt asking it to 'be efficient'.
یہ پکی حدیں ہیں، مشورے نہیں۔ اگر ایجنٹ بار بار چکر لگائے یا زیادہ خرچ کرے تو حل یہی سخت حد ہے، پرامپٹ میں ’کفایت کرو‘ نہیں۔
Task 1.7 — session resume, fork & checkpointing
Resume a prior session, fork it into a parallel branch, or checkpoint files so you can rewind. This is the config behind Task 1.7 (resume / fork).
continue_conversation=False, resume=None, # session ID to resume session_id=None, # explicit UUID for this session fork_session=False, # if resuming, fork into a NEW session ID enable_file_checkpointing=True # enables client.rewind_files()
fork_session=True while resuming branches the shared history into independent lines — the exam's 'explore two strategies from one analysis' pattern, where neither branch pollutes the other. On resume after edits, you must re-inform the agent about files that changed.
resume کے دوران fork_session=True مشترکہ تاریخ سے الگ الگ شاخیں بناتا ہے — ’ایک تجزیے سے دو حکمتِ عملی‘۔ فائلیں بدلی ہوں تو resume پر ایجنٹ کو بتانا لازم ہے۔
Task 1.5 — hooks & deterministic enforcement
Hooks run your code at fixed points in the loop (e.g. before/after a tool). Because they execute every time, they GUARANTEE behavior the prompt can only encourage.
hooks={}, # dict[HookEvent, list[HookMatcher]] — e.g. PreToolUse / PostToolUse matchersA PreToolUse hook can veto or reroute a call before it runs (e.g. 'refunds over $500 go to a human'); a PostToolUse hook can normalize heterogeneous tool outputs into one shape. Hook = runs every time (a guarantee). Prompt = followed most of the time (a tendency).
PreToolUse ہک کال چلنے سے پہلے روک یا موڑ سکتا ہے؛ PostToolUse مختلف نتائج کو ایک شکل میں لاتا ہے۔ ہک ہر بار چلتا ہے (ضمانت)، پرامپٹ اکثر (رجحان)۔
Task 1.4 — subagent invocation, context passing & spawning
The full shape of a subagent. description and prompt are required — the first tells the coordinator WHEN to use it, the second IS its system prompt. Everything else scopes and bounds it.
subagent = AgentDefinition(
description="Reviews pull requests for security and style issues", # required — when Claude picks this subagent
prompt="You are a strict senior code reviewer. Flag security issues first.", # required — its system prompt
tools=["Read", "Grep", "Glob"], # allowed tools; omit to inherit everything available to subagents
disallowedTools=["Bash", "Write"], # removes tools; also accepts mcp__server / mcp__* patterns
model="sonnet", # alias or full ID; omit = use main model
skills=["docx", "pdf-reading"], # preloaded at startup (others still invocable via the Skill tool)
memory="project", # "user" | "project" | "local"
mcpServers=["calc"], # server names or inline {name: config} dicts
initialPrompt="Start by summarizing the diff.", # auto-submitted first turn IF run as main-thread agent
maxTurns=15,
background=False, # True = run as a non-blocking background task when invoked
effort="high", # named level or integer
permissionMode="dontAsk", # this agent's own tool-execution permission mode
)Note the field names differ from ClaudeAgentOptions: here allowed tools is tools (not allowed_tools), and keys are camelCase (disallowedTools, mcpServers, maxTurns). Scoping tools per subagent is how you stop a reviewer from, say, running Bash. Because context is isolated, the coordinator must inline everything the subagent needs into its prompt.
فیلڈ نام مختلف ہیں: یہاں اجازت والے ٹول tools ہیں (نہ کہ allowed_tools)، اور کیمل کیس (disallowedTools, mcpServers)۔ ہر سب ایجنٹ کے ٹول محدود کرنا ہی غلط استعمال روکتا ہے۔ سیاق الگ ہے، اس لیے ضروری معلومات پرامپٹ میں ڈالنی پڑتی ہیں۔