Skip to content

Commit 028d591

Browse files
authored
feat(types): add disallowedTools, maxTurns, initialPrompt to AgentDefinition (#759)
Brings `AgentDefinition` to parity with the TypeScript SDK. ## New fields | Field | Type | Purpose | |---|---|---| | `disallowedTools` | `list[str] \| None` | Tool names to explicitly block for this agent | | `maxTurns` | `int \| None` | Cap on agentic API round-trips before stopping | | `initialPrompt` | `str \| None` | Auto-submitted first turn when used as main-thread agent | ## Changed - `model` widened from `Literal["sonnet", "opus", "haiku", "inherit"]` to `str` — TS accepts full model IDs (e.g. `claude-opus-4-5`) in addition to aliases. Existing callers using the literal values are unaffected. ## Not included - `criticalSystemReminder_EXPERIMENTAL` — experimental, skipping for now - Frontmatter-only fields (`background`, `permissionMode`, `hooks`, `effort`, `isolation`) — neither SDK exposes these yet; separate effort ## Transport Serialization in `client.py` already uses `asdict()` with a None-filter, so new optional fields flow to the initialize request without transport changes. Field names are camelCase to match the CLI's expected JSON keys (same pattern as `mcpServers` from #684).
1 parent f9fc8e0 commit 028d591

2 files changed

Lines changed: 47 additions & 1 deletion

File tree

src/claude_agent_sdk/types.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,15 @@ class AgentDefinition:
6767
description: str
6868
prompt: str
6969
tools: list[str] | None = None
70-
model: Literal["sonnet", "opus", "haiku", "inherit"] | None = None
70+
disallowedTools: list[str] | None = None # noqa: N815
71+
# Model alias ("sonnet", "opus", "haiku", "inherit") or a full model ID.
72+
model: str | None = None
7173
skills: list[str] | None = None
7274
memory: Literal["user", "project", "local"] | None = None
7375
# Each entry is a server name (str) or an inline {name: config} dict.
7476
mcpServers: list[str | dict[str, Any]] | None = None # noqa: N815
77+
initialPrompt: str | None = None # noqa: N815
78+
maxTurns: int | None = None # noqa: N815
7579

7680

7781
# Permission Update types (matching TypeScript SDK)

tests/test_types.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,3 +496,45 @@ def test_mcp_servers_serializes_as_camelcase(self):
496496
assert "mcp_servers" not in payload
497497
assert payload["mcpServers"][0] == "slack"
498498
assert payload["mcpServers"][1]["local"]["command"] == "python"
499+
500+
def test_disallowed_tools_and_max_turns_serialize_as_camelcase(self):
501+
"""CLI expects ``disallowedTools`` and ``maxTurns`` (camelCase)."""
502+
from claude_agent_sdk import AgentDefinition
503+
504+
agent = AgentDefinition(
505+
description="test",
506+
prompt="p",
507+
disallowedTools=["Bash", "Write"],
508+
maxTurns=10,
509+
)
510+
payload = self._serialize(agent)
511+
512+
assert payload["disallowedTools"] == ["Bash", "Write"]
513+
assert "disallowed_tools" not in payload
514+
assert payload["maxTurns"] == 10
515+
assert "max_turns" not in payload
516+
517+
def test_initial_prompt_serializes_as_camelcase(self):
518+
from claude_agent_sdk import AgentDefinition
519+
520+
agent = AgentDefinition(
521+
description="test",
522+
prompt="p",
523+
initialPrompt="/review-pr 123",
524+
)
525+
payload = self._serialize(agent)
526+
527+
assert payload["initialPrompt"] == "/review-pr 123"
528+
assert "initial_prompt" not in payload
529+
530+
def test_model_accepts_full_model_id(self):
531+
from claude_agent_sdk import AgentDefinition
532+
533+
agent = AgentDefinition(
534+
description="test",
535+
prompt="p",
536+
model="claude-opus-4-5",
537+
)
538+
payload = self._serialize(agent)
539+
540+
assert payload["model"] == "claude-opus-4-5"

0 commit comments

Comments
 (0)