Skip to content

Export EffortLevel as a named TypeAlias from claude_agent_sdk.types #938

@loganrosen

Description

@loganrosen

Summary

The effort field's Literal["low", "medium", "high", "xhigh", "max"] is currently inlined at every use site in src/claude_agent_sdk/types.py (lines 99 on ClaudeAgentOptions and 1867 on ThinkingConfig).

It would be helpful for downstream consumers if it were exported as a named TypeAlias, e.g.:

EffortLevel: TypeAlias = Literal["low", "medium", "high", "xhigh", "max"]

…then referenced from the two existing use sites.

Why

  1. Consistency with existing pattern. The same file already exports several similar small literals as named aliases:

    • PermissionMode (line 24)
    • SdkBeta (line 29)
    • SettingSource (line 32)
    • PermissionUpdateDestination (line 103)
    • PermissionBehavior (line 107)
    • McpServerConnectionStatus (line 654)
    • …etc.

    effort is the same shape but inlined instead.

  2. Single source of truth for downstream wrappers. Anyone wrapping the SDK (LinkedIn-internal LIPA in our case, but also any third-party agent framework) currently has two unattractive options:

    • Inline the same Literal[...] in their own config field — duplicated source of truth, drifts on SDK updates.
    • Write their own internal alias — same drift problem.

    With an exported EffortLevel, consumers can write from claude_agent_sdk import EffortLevel and stay in sync automatically.

  3. The literal is moving. "xhigh" was added between 0.1.71 and 0.1.77 (referenced in ClaudeAgentOptions.effort typings are outdated, and CLI validation failures are surfaced as opaque ProcessError #834). That's a real-world example of the drift consumers would otherwise have to track manually. A named alias makes every SDK update propagate automatically.

Suggested change

# In src/claude_agent_sdk/types.py, near the other TypeAliases at the top:
EffortLevel: TypeAlias = Literal["low", "medium", "high", "xhigh", "max"]

# Then at line 99 (ClaudeAgentOptions):
effort: EffortLevel | int | None = None

# And at line 1867 (ThinkingConfig):
effort: EffortLevel | None = None

And export EffortLevel from __init__.py alongside the other named types.

Related

Happy to send a PR if this is welcome.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions