Skip to content

Prompts & Retry API

This page documents the exported prompt builders, the static prompt/tool description constants, and the auto-retry helpers.

Prompt Builders

get_subagent_system_prompt

subagents_pydantic_ai.get_subagent_system_prompt(configs, include_dual_mode=False)

Generate the system prompt section describing available subagents.

Parameters:

Name Type Description Default
configs list[SubAgentConfig]

Subagent configurations to list.

required
include_dual_mode bool

Append DUAL_MODE_SYSTEM_PROMPT, explaining sync versus background execution. Off by default because TASK_TOOL_DESCRIPTION already covers execution modes where the model needs them, and repeating it in the system prompt is wasted context. The parameter used to be accepted and ignored.

False

Returns:

Type Description
str

Formatted system prompt section.

Example
Python
configs = [
    SubAgentConfig(
        name="researcher",
        description="Researches topics",
        instructions="...",
    ),
]
prompt = get_subagent_system_prompt(configs)
Source code in src/subagents_pydantic_ai/prompts.py
Python
def get_subagent_system_prompt(
    configs: list[SubAgentConfig],
    include_dual_mode: bool = False,
) -> str:
    """Generate the system prompt section describing available subagents.

    Args:
        configs: Subagent configurations to list.
        include_dual_mode: Append `DUAL_MODE_SYSTEM_PROMPT`, explaining sync
            versus background execution. Off by default because
            `TASK_TOOL_DESCRIPTION` already covers execution modes where the
            model needs them, and repeating it in the system prompt is wasted
            context. The parameter used to be accepted and ignored.

    Returns:
        Formatted system prompt section.

    Example:
        ```python
        configs = [
            SubAgentConfig(
                name="researcher",
                description="Researches topics",
                instructions="...",
            ),
        ]
        prompt = get_subagent_system_prompt(configs)
        ```
    """
    lines = [
        "## Available Subagents",
        "",
        "Use the `task` tool to delegate work to these subagents:",
        "",
    ]

    for config in configs:
        line = f"- **{config['name']}**: {config['description']}"
        if config.get("can_ask_questions") is False:
            line += " *(cannot ask clarifying questions)*"
        lines.append(line)

    if include_dual_mode:
        lines.extend(["", DUAL_MODE_SYSTEM_PROMPT])

    return "\n".join(lines)

get_task_instructions_prompt

subagents_pydantic_ai.get_task_instructions_prompt(task_description, can_ask_questions=True, max_questions=None)

Generate the task instructions for a subagent.

Parameters:

Name Type Description Default
task_description str

The task to perform.

required
can_ask_questions bool

Whether the subagent can ask the parent questions.

True
max_questions int | None

Maximum number of questions allowed.

None

Returns:

Type Description
str

Formatted task instructions.

Source code in src/subagents_pydantic_ai/prompts.py
Python
def get_task_instructions_prompt(
    task_description: str,
    can_ask_questions: bool = True,
    max_questions: int | None = None,
) -> str:
    """Generate the task instructions for a subagent.

    Args:
        task_description: The task to perform.
        can_ask_questions: Whether the subagent can ask the parent questions.
        max_questions: Maximum number of questions allowed.

    Returns:
        Formatted task instructions.
    """
    lines = ["## Your Task", "", task_description, ""]

    if can_ask_questions:
        lines.append("## Asking Questions")
        lines.append("If you need clarification, use the `ask_parent` tool.")
        if max_questions is not None:
            lines.append(f"You may ask up to {max_questions} questions.")
        lines.append("Keep questions specific and essential.")
    else:
        lines.append("## Note")
        lines.append("Complete this task using your best judgment.")
        lines.append("You cannot ask the parent for clarification.")

    return "\n".join(lines)

Prompt & Description Constants

These string constants are exported for inspection and overriding. The *_DESCRIPTION constants are the default model-facing tool descriptions used by create_subagent_toolset (override them per-tool via its descriptions argument).

subagents_pydantic_ai.SUBAGENT_SYSTEM_PROMPT = 'You are a specialized subagent working on a delegated task.\n\n## Your Role\nYou have been spawned by a parent agent to handle a specific task. Focus entirely\non completing the assigned task to the best of your ability.\n\n## Communication\n- If you need clarification, use the `ask_parent` tool to ask the parent agent\n- Keep questions specific and actionable\n- Do not ask unnecessary questions - use your judgment when possible\n- If you cannot complete a task, explain why clearly\n\n## Task Completion\n- Complete the task thoroughly before returning\n- Provide clear, structured results\n- If the task cannot be completed, explain what was attempted and why it failed\n' module-attribute

subagents_pydantic_ai.DUAL_MODE_SYSTEM_PROMPT = '## Subagent Execution Modes\n\nYou can delegate tasks to subagents in two modes:\n\n### Sync Mode (Default)\n- Use for simple, quick tasks\n- Use when you need the result immediately\n- Use when the task requires back-and-forth communication\n- The task runs and you wait for the result\n\n### Async Mode (Background)\n- Use for complex, long-running tasks\n- Use when you can continue with other work while waiting\n- Use for tasks that can run independently\n- Returns a task handle immediately - check status later\n' module-attribute

subagents_pydantic_ai.DEFAULT_GENERAL_PURPOSE_DESCRIPTION = 'A general-purpose agent for a wide variety of tasks.\nUse this when no specialized subagent matches the task requirements.\nCapable of research, analysis, writing, and problem-solving.' module-attribute

subagents_pydantic_ai.TASK_TOOL_DESCRIPTION = 'Delegate a task to a specialized subagent. The subagent runs independently with its own context and tools, and returns a result when done.\n\n## When to use\n- Complex multi-step tasks that can run independently from your main work\n- Research or exploration tasks (e.g., "find all usages of function X", "understand how module Y works") — delegate so you can continue other work\n- Multiple independent subtasks that can run in parallel — launch several subagents simultaneously for maximum efficiency\n- Tasks that require deep focus on a single area while you handle the big picture\n\n## When NOT to use\n- Trivial tasks you can do faster yourself (single file read, simple grep)\n- Tasks that require your full conversation context — subagents don\'t share your message history\n- Tasks that need back-and-forth with the user — subagents work autonomously\n\n## Usage notes\n- **Be specific**: Subagents don\'t share your context. Include all necessary details in the description: file paths, function names, expected behavior, constraints. The more specific, the better the result.\n- **Launch in parallel**: When you have multiple independent tasks, call `task()` multiple times in a single response. They run concurrently.\n- **Synthesize results**: When subagents return, combine and analyze their results before presenting to the user. Don\'t just relay raw output.\n- **Choose the right subagent**: Match the subagent_type to the task. Use "general-purpose" when no specialized subagent fits.\n- **Continue intentionally**: When a result includes `Chat Trace ID: <id>`, pass that value as `chat_trace_id` only when you want the same subagent to resume that conversation. Omit `chat_trace_id` to start a new conversation. A trace can only be continued after its current task finishes, and only with the same subagent; continuing a busy or unknown trace returns an error.\n\n## Execution modes\n- **"sync"** (default): Blocks until the subagent completes. Use for quick tasks or when you need the result immediately.\n- **"async"**: Returns a task handle immediately. Use for long-running tasks where you can continue other work. Check results with `check_task()` or wait with `wait_tasks()`.\n- **"auto"**: Automatically picks sync or async based on task complexity.\n\nReturns:\n- In sync mode: The subagent\'s response as a string.\n- In async mode: A task handle with task_id for status checking.\n' module-attribute

subagents_pydantic_ai.CHECK_TASK_DESCRIPTION = "Check the status of a background (async) task and get its result if completed.\n\nUse this after launching async tasks to see if they're done. Returns the task's current status, plus its result when completed, its error when failed, its pending question when waiting for an answer, and why it stopped when cancelled. The result is always returned in full, so call this when a `wait_tasks` listing showed a truncated one." module-attribute

subagents_pydantic_ai.ANSWER_SUBAGENT_DESCRIPTION = 'Answer a question from a background subagent that is waiting for clarification.\n\nWhen a task has status WAITING_FOR_ANSWER, the subagent needs information from you before it can continue. Provide a clear, specific answer.' module-attribute

subagents_pydantic_ai.LIST_ACTIVE_TASKS_DESCRIPTION = 'List all currently active background tasks with their status.\n\nUse this to see what async tasks are running and their current state.' module-attribute

subagents_pydantic_ai.WAIT_TASKS_DESCRIPTION = 'Wait for one or more background tasks to finish before continuing.\n\nA task is "finished" when it is completed, failed, or cancelled.\n\n## Modes\n\n- **mode="all"** (default): block until every task in `task_ids` is finished, or the timeout is reached. Use when you genuinely need every result together before the next step (e.g. final synthesis across all subagents).\n- **mode="any"**: return as soon as ONE task finishes. Use when the subagents are independent and you can start acting on each finisher immediately — this avoids stalling on the slowest task. After reacting to the finisher, call `wait_tasks` again on the remaining ids (or use `check_task`) to handle the rest.\n\n## When to prefer `mode="any"`\n\nWhen you\'ve dispatched several async tasks in parallel and any individual result is independently useful (e.g. routing decisions, progressive synthesis, fan-out research). Reactive orchestration is almost always faster than waiting on the slowest agent.\n\n## Output\n\nThe result lists every requested task with its current state and a header showing `mode`, `<finished>/<total> finished`, and how many are still running. Unfinished tasks remain in the background — you can keep working or wait on them again later.\n\nA long result may be cut here to save context, in which case it ends with an explicit truncation marker. That marker is a display limit on this listing, never an incomplete subagent answer: the full text is stored and `check_task` returns it. Never re-delegate a task to "finish" a result that carries the marker.' module-attribute

subagents_pydantic_ai.SOFT_CANCEL_TASK_DESCRIPTION = 'Request cooperative cancellation of a background task. The subagent will be notified and can clean up before stopping. Use this for graceful cancellation.' module-attribute

subagents_pydantic_ai.HARD_CANCEL_TASK_DESCRIPTION = "Immediately cancel a background task. The task will be forcefully stopped. Use only when soft cancellation doesn't work or immediate stopping is required." module-attribute