> ## Documentation Index
> Fetch the complete documentation index at: https://docs.symbolica.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Prompting

export const LATEST_ANTHROPIC_MODEL = "anthropic/claude-opus-4.6";

export const LATEST_OPENAI_MODEL = "openai/gpt-5.2";

export const CheckboxItem = ({children}) => <div style={{
  display: 'flex',
  alignItems: 'flex-start',
  gap: '8px',
  marginBottom: '0.25rem'
}}>
    <span style={{
  marginTop: '-2px'
}}><input type="checkbox" /></span>
    <span>{children}</span>
  </div>;

<AccordionGroup>
  <Accordion title={<span>Prompt engineering for <strong>OpenAI</strong> models</span>} icon="openai" iconType="brands">
    When using OpenAI models (<code>{LATEST_OPENAI_MODEL}</code> etc.) with the Agentica SDK, apply these [proven strategies](https://platform.openai.com/docs/guides/prompt-engineering):

    **Writing Agentic Function Docstrings**

    <CodeGroup>
      ```python Python theme={null}
      # Bad - Vague docstring
      @agentic()
      async def analyze(text: str) -> dict:
          """Analyze text"""
          ...

      # Good - Clear, specific docstring
      @agentic()
      async def analyze(text: str) -> dict[str, Any]:
          """
          Analyze the sentiment, key entities, and main topics in the text.
          Return a dict with 'sentiment' (positive/negative/neutral),
          'entities' (list of names/places/orgs), and 'topics' (list of main themes).
          """
          ...
      ```

      ```typescript TypeScript theme={null}
      // Bad - Vague description
      async function analyze(text: string): Promise<object> {
          return agentic("Analyze text", { text });
      }

      // Good - Clear, specific description
      async function analyze(text: string): Promise<AnalysisResult> {
          return agentic(
              "Analyze sentiment (positive/negative/neutral), extract entities (names, places, orgs), and identify main topics from the text",
              { text }
          );
      }
      ```
    </CodeGroup>

    **Crafting Agent Premises**

    <CodeGroup>
      ```python Python theme={null}
      # Bad - Generic premise
      agent = await spawn(premise="You are helpful.")

      # Good - Specific premise with clear role and constraints
      agent = await spawn(
          premise="""
          You are a data analyst specializing in customer feedback.
          Always provide numerical confidence scores (0-1) with your conclusions.
          When uncertain, explicitly state your assumptions.
          """
      )
      ```

      ```typescript TypeScript theme={null}
      // Bad - Generic premise
      const agent = await spawn({ premise: "You are helpful." });

      // Good - Specific premise with clear role and constraints
      const agent = await spawn({
          premise: `You are a data analyst specializing in customer feedback.
          Always provide numerical confidence scores (0-1) with your conclusions.
          When uncertain, explicitly state your assumptions.`
      });
      ```
    </CodeGroup>

    **Request Step-by-Step Reasoning**

    For complex tasks, explicitly ask for reasoning in your docstrings or premises:

    <CodeGroup>
      ```python Python theme={null}
      @agentic()
      async def solve_problem(problem: str) -> dict[str, Any]:
          """
          Solve the math problem step by step.
          First, identify what's being asked.
          Then, break down the solution into steps.
          Finally, provide the answer with your reasoning.
          """
          ...
      ```

      ```typescript TypeScript theme={null}
      async function solveProblem(problem: string): Promise<Solution> {
          return agentic(
              "Solve step by step: 1) Identify what's asked, 2) Show your work, 3) Provide final answer",
              { problem }
          );
      }
      ```
    </CodeGroup>

    **Leverage Scope Effectively**

    Provide focused, relevant tools rather than entire SDKs:

    <CodeGroup>
      ```python Python theme={null}
      from slack_sdk import WebClient

      slack = WebClient(token=TOKEN)

      # Good - Extract only what you need
      @agentic(slack.users_list, slack.chat_postMessage)
      async def notify_team(message: str) -> None:
          """Send message to all active team members."""
          ...
      ```

      ```typescript TypeScript theme={null}
      import { WebClient } from '@slack/web-api';

      const slack = new WebClient(TOKEN);

      // Good - Extract only what you need
      async function notifyTeam(message: string): Promise<void> {
          return agentic(
              "Send message to all active team members",
              {
                  message,
                  listUsers: slack.users.list.bind(slack.users),
                  postMessage: slack.chat.postMessage.bind(slack.chat)
              }
          );
      }
      ```
    </CodeGroup>

    **Type Hints are Instructions**

    OpenAI models excel at following type hints -- use them to guide output:

    <CodeGroup>
      ```python Python theme={null}
      from typing import Literal

      @agentic()
      async def classify(text: str) -> Literal['urgent', 'normal', 'low']:
          """Classify the priority of this support ticket."""
          ...
      ```

      ```typescript TypeScript theme={null}
      type Priority = 'urgent' | 'normal' | 'low';

      async function classify(text: string): Promise<Priority> {
          return agentic<Priority>("Classify the priority of this support ticket", { text });
      }
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title={<span>Prompt engineering for <strong>Anthropic</strong> models</span>} icon="https://mintcdn.com/symbolica/K5J3rY_7011ITyU6/images/anthropic-icon.svg?fit=max&auto=format&n=K5J3rY_7011ITyU6&q=85&s=284d31a0cca956a2f40e2955bb433c43" data-og-width="24" width="24" data-og-height="24" height="24" data-path="images/anthropic-icon.svg" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/symbolica/K5J3rY_7011ITyU6/images/anthropic-icon.svg?w=280&fit=max&auto=format&n=K5J3rY_7011ITyU6&q=85&s=4b3e5173c0e1e44e57f0c32529aa6bda 280w, https://mintcdn.com/symbolica/K5J3rY_7011ITyU6/images/anthropic-icon.svg?w=560&fit=max&auto=format&n=K5J3rY_7011ITyU6&q=85&s=775a69ad8d86749824082353211f14a5 560w, https://mintcdn.com/symbolica/K5J3rY_7011ITyU6/images/anthropic-icon.svg?w=840&fit=max&auto=format&n=K5J3rY_7011ITyU6&q=85&s=0949777980f459d523fc0514ad8bccec 840w, https://mintcdn.com/symbolica/K5J3rY_7011ITyU6/images/anthropic-icon.svg?w=1100&fit=max&auto=format&n=K5J3rY_7011ITyU6&q=85&s=b5756a9205dadb2ee5b792266cdba941 1100w, https://mintcdn.com/symbolica/K5J3rY_7011ITyU6/images/anthropic-icon.svg?w=1650&fit=max&auto=format&n=K5J3rY_7011ITyU6&q=85&s=8962a7d0f589a9e36a11264b4a84bc3f 1650w, https://mintcdn.com/symbolica/K5J3rY_7011ITyU6/images/anthropic-icon.svg?w=2500&fit=max&auto=format&n=K5J3rY_7011ITyU6&q=85&s=7f6fe6c245ba5cbfcd7aa088906b9361 2500w">
    When using Anthropic models (<code>{LATEST_ANTHROPIC_MODEL}</code> etc.) with the Agentica SDK, leverage these [Claude-specific strengths](https://docs.claude.com/en/docs/build-with-claude/prompt-engineering/overview):

    **XML Tags in Docstrings**

    Claude excels at parsing XML structure -- use it in complex agentic functions:

    <CodeGroup>
      ```python Python theme={null}
      @agentic()
      async def extract_and_validate(document: str, schema: dict) -> dict:
          """
          Extract structured data from the document and validate against schema.

          <instructions>
          1. Parse the document and extract fields matching the schema
          2. Validate each field against schema constraints
          3. Return extracted data with validation status
          </instructions>

          <output_format>
          Return dict with 'data' (extracted fields) and 'valid' (bool)
          </output_format>
          """
          ...
      ```

      ```typescript TypeScript theme={null}
      async function extractAndValidate(document: string, schema: object): Promise<Result> {
          return agentic(`Extract structured data from document and validate against schema.

          <instructions>
          1. Parse the document and extract fields matching the schema
          2. Validate each field against schema constraints
          3. Return extracted data with validation status
          </instructions>

          <output_format>
          Return object with 'data' (extracted fields) and 'valid' (boolean)
          </output_format>`,
              { document, schema }
          );
      }
      ```
    </CodeGroup>

    **Rich Agent Premises**

    Claude responds well to detailed role definitions:

    <CodeGroup>
      ```python Python theme={null}
      agent = await spawn(
          premise="""
          You are a senior software architect with expertise in distributed systems.

          <role>
          - Analyze system designs for scalability issues
          - Suggest concrete improvements with trade-offs
          - Consider cost, latency, and reliability
          </role>

          <style>
          - Be direct and technical
          - Provide specific code/config examples when helpful
          - Acknowledge uncertainties explicitly
          </style>
          """,
          model="anthropic/claude-opus-4.6"
      )
      ```

      ```typescript TypeScript theme={null}
      const agent = await spawn({
          premise: `You are a senior software architect with expertise in distributed systems.

          <role>
          - Analyze system designs for scalability issues
          - Suggest concrete improvements with trade-offs
          - Consider cost, latency, and reliability
          </role>

          <style>
          - Be direct and technical
          - Provide specific code/config examples when helpful
          - Acknowledge uncertainties explicitly
          </style>`,
          model: "anthropic/claude-opus-4.6"
      });
      ```
    </CodeGroup>

    **Chain of Thought Prompts**

    Claude's reasoning improves dramatically with explicit thinking requests:

    <CodeGroup>
      ```python Python theme={null}
      @agentic()
      async def debug_issue(code: str, error: str) -> dict[str, str]:
          """
          Debug the code issue by thinking through it step by step.

          Before providing a solution:
          1. Analyze what the code is trying to do
          2. Identify why the error occurs
          3. Consider multiple potential fixes
          4. Choose the best fix with explanation

          Return dict with 'analysis' and 'fix' keys.
          """
          ...
      ```

      ```typescript TypeScript theme={null}
      interface DebugResult {
          analysis: string;
          fix: string;
      }

      async function debugIssue(code: string, error: string): Promise<DebugResult> {
          return agentic<DebugResult>(
              `Debug by thinking step by step:
              1. Analyze what the code tries to do
              2. Identify why the error occurs
              3. Consider multiple potential fixes
              4. Choose the best fix with explanation

              Return analysis and fix.`,
              { code, error }
          );
      }
      ```
    </CodeGroup>

    **Long Context Utilization**

    Claude handles large contexts exceptionally well -- structure them clearly:

    <CodeGroup>
      ```python Python theme={null}
      @agentic()
      async def analyze_codebase(files: dict[str, str]) -> dict:
          """
          Analyze the entire codebase for security issues.

          <critical_instructions>
          Focus on: SQL injection, XSS, auth bypasses, secrets in code
          </critical_instructions>

          Process each file systematically. Look for patterns across files.

          <critical_instructions>
          Return findings with file paths and severity (critical/high/medium/low)
          </critical_instructions>
          """
          ...
      ```

      ```typescript TypeScript theme={null}
      async function analyzeCodebase(files: Record<string, string>): Promise<SecurityReport> {
          return agentic(
              `Analyze the entire codebase for security issues.

              <critical_instructions>
              Focus on: SQL injection, XSS, auth bypasses, secrets in code
              </critical_instructions>

              Process each file systematically. Look for patterns across files.

              <critical_instructions>
              Return findings with file paths and severity levels
              </critical_instructions>`,
              { files }
          );
      }
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title={<span><strong>Key Distinctions</strong> & Takeaways</span>} icon="key">
    **Prompting Style Differences**

    **OpenAI Models** (<code>{LATEST_OPENAI_MODEL}</code> etc.):

    * **Concise instructions.** Works well with shorter, direct docstrings and premises.
    * **Delimiters.** Use `###` or `"""` to separate sections in complex prompts.
    * **Step-by-step explicit.** Benefits from phrases like "First... Then... Finally..."
    * **Function-oriented.** Natural fit for task decomposition and tool use.

    **Anthropic Models** (<code>{LATEST_ANTHROPIC_MODEL}</code> etc.):

    * **XML tags preferred.** Use `<instructions>`, `<context>`, `<examples>` for structure.
    * **Detailed premises.** Responds well to longer, more elaborate role definitions.
    * **Chain of thought.** Explicitly request thinking with "Before answering, think step by step..."
    * **Long context friendly.** Can handle very large prompts and scope effectively.

    **Universal Agentica SDK Best Practices**

    Regardless of model choice:

    **1. Write Clear Docstrings/Descriptions.** Be specific about what, how, and what format to return.

    <CodeGroup>
      ```python Python theme={null}
      # Agentic functions: detailed docstrings
      @agentic()
      async def process(data: str) -> Result:
          """What, how, and what format to return"""
          ...

      # Agents: specific premises
      agent = await spawn(premise="Clear role + constraints")
      ```

      ```typescript TypeScript theme={null}
      // Agentic functions: detailed descriptions
      async function process(data: string): Promise<Result> {
          return agentic("What, how, and what format", { data });
      }

      // Agents: specific premises
      const agent = await spawn({ premise: "Clear role + constraints" });
      ```
    </CodeGroup>

    **2. Use Strong Type Hints.** Types guide agents and ensure type-safe returns.

    <CodeGroup>
      ```python Python theme={null}
      from typing import Literal
      from pydantic import BaseModel

      class Analysis(BaseModel):
          sentiment: Literal['positive', 'negative', 'neutral']
          confidence: float

      @agentic()
      async def analyze(text: str) -> Analysis:
          """Return sentiment analysis"""
          ...
      ```

      ```typescript TypeScript theme={null}
      interface Analysis {
          sentiment: 'positive' | 'negative' | 'neutral';
          confidence: number;
      }

      async function analyze(text: string): Promise<Analysis> {
          return agentic<Analysis>("Return sentiment analysis", { text });
      }
      ```
    </CodeGroup>

    **3. Provide Focused Scope.** Only include tools/data agents need for the specific task, not entire objects or SDKs.

    **4. Request Reasoning for Complex Tasks.** Add "step by step" or "think through" to prompts for better accuracy on hard problems.

    **5. Test with Real Examples.** Validate agentic functions and agents with actual use cases before production.

    ### Choosing Models with the Agentica SDK

    **Consider OpenAI when:**

    * Your prompts are concise and task-focused
    * You're using structured delimiters for prompt sections
    * Example: `model="openai/gpt-5"`

    **Consider Anthropic when:**

    * Your prompts benefit from XML structure
    * You're working with very large context in scope
    * You want detailed, persona-driven agents
    * Example: `model="anthropic/claude-opus-4.6"`

    **Prompting Approach:**

    | Prompt Style                | Better Match     |
    | --------------------------- | ---------------- |
    | Short, focused instructions | OpenAI models    |
    | XML-structured prompts      | Anthropic models |
    | Large context (50K+ tokens) | Anthropic models |
    | Detailed role definitions   | Anthropic models |
    | Task decomposition patterns | OpenAI models    |
  </Accordion>
</AccordionGroup>

### Be Specific

Vague prompts lead to inconsistent results. Agents need clear instructions about what you want, how you want it, and what format to return. Think of your docstring as a specification, not just a description.

**Bad approach**: Generic verbs without details.

<CodeGroup>
  ```python Python theme={null}
  @agentic()
  async def summarize(text: str) -> str:
      """Summarize the text"""
      ...
  ```

  ```typescript TypeScript theme={null}
  async function summarize(text: string): Promise<string> {
    return agentic("Summarize the text", { text });
  }
  ```
</CodeGroup>

**Good approach**: Specify length, focus, and style.

<CodeGroup>
  ```python Python theme={null}
  @agentic()
  async def summarize(text: str) -> str:
      """
      Create a 2-3 sentence summary of the text.
      Focus on the main argument and key supporting points.
      Use objective language without opinion.
      """
      ...
  ```

  ```typescript TypeScript theme={null}
  async function summarize(text: string): Promise<string> {
    return agentic(
      `Create a 2-3 sentence summary of the text.
       Focus on the main argument and key supporting points.
       Use objective language without opinion.`,
      { text }
    );
  }
  ```
</CodeGroup>

When behavior or style matters beyond just the output structure, specify it clearly. Types tell agents what to return, but your prompt tells it how to get there.

<CodeGroup>
  ```python Python theme={null}
  @agentic()
  async def extract_sql(user_request: str, schema: dict) -> str:
      """
      Generate a SQL query from the user's natural language request.

      Requirements:
      - Use only SELECT statements (no INSERT, UPDATE, DELETE)
      - Always include LIMIT clauses to prevent large result sets
      - Use table aliases for readability
      - When joining tables, prefer INNER JOIN over implicit joins
      - Add comments explaining complex WHERE clauses

      Return valid PostgreSQL syntax.
      """
      ...
  ```

  ```typescript TypeScript theme={null}
  async function extractSql(userRequest: string, schema: object): Promise<string> {
    return agentic<string>(
      `Generate a SQL query from the user's natural language request.

      Requirements:
      - Use only SELECT statements (no INSERT, UPDATE, DELETE)
      - Always include LIMIT clauses to prevent large result sets
      - Use table aliases for readability
      - When joining tables, prefer INNER JOIN over implicit joins
      - Add comments explaining complex WHERE clauses

      Return valid PostgreSQL syntax.`,
      { userRequest, schema }
    );
  }
  ```
</CodeGroup>

### Include Examples

When you need specific formatting or a particular style, showing examples is more effective than describing the desired output in words. Models learn patterns quickly from concrete examples.

Use examples for tasks where the output has specific structure, like generating changelog entries:

<CodeGroup>
  ```python Python theme={null}
  @agentic()
  async def write_changelog_entry(commit_messages: list[str]) -> str:
      """
      Write a changelog entry from commit messages.

      Example input: ["fix: resolve login timeout", "feat: add dark mode"]
      Example output:
      ### Features
      - Added dark mode support

      ### Bug Fixes
      - Fixed login timeout issue

      Follow this format exactly.
      """
      ...
  ```

  ```typescript TypeScript theme={null}
  async function writeChangelogEntry(commitMessages: string[]): Promise<string> {
    return agentic(
      `Write a changelog entry from commit messages.

      Example input: ["fix: resolve login timeout", "feat: add dark mode"]
      Example output:
      ### Features
      - Added dark mode support

      ### Bug Fixes
      - Fixed login timeout issue

      Follow this format exactly.`,
      { commitMessages }
    );
  }
  ```
</CodeGroup>

Multiple examples help establish patterns, especially for formatting that varies by input:

<CodeGroup>
  ```python Python theme={null}
  @agentic()
  async def format_currency(amount: float, currency: str) -> str:
      """
      Format a currency amount for display.

      Examples:
      - format_currency(1234.50, "USD") → "$1,234.50"
      - format_currency(999.99, "EUR") → "€999.99"
      - format_currency(50, "GBP") → "£50.00"

      Always include the currency symbol and exactly 2 decimal places.
      """
      ...
  ```

  ```typescript TypeScript theme={null}
  async function formatCurrency(amount: number, currency: string): Promise<string> {
    return agentic(
      `Format a currency amount for display.

      Examples:
      - $1,234.50 for 1234.50 USD
      - €999.99 for 999.99 EUR
      - £50.00 for 50 GBP

      Always include the currency symbol and exactly 2 decimal places.`,
      { amount, currency }
    );
  }
  ```
</CodeGroup>

### Define Constraints

Agents need explicit rules for handling edge cases and ambiguous inputs. Without clear constraints, you'll get inconsistent behavior when inputs don't match the happy path.

When your task involves categorization or decision-making, spell out the criteria:

<CodeGroup>
  ```python Python theme={null}
  from typing import Literal

  @agentic()
  async def categorize_severity(error_message: str, stack_trace: str) -> Literal['critical', 'high', 'medium', 'low']:
      """
      Categorize error severity.

      Constraints:
      - Return 'critical' if: data loss, security breach, system crash
      - Return 'high' if: feature unusable, affects multiple users
      - Return 'medium' if: degraded performance, workaround available
      - Return 'low' if: cosmetic issue, minimal impact

      Edge cases:
      - If stack_trace is empty, base decision on error_message alone
      - Database errors are at minimum 'high' severity
      - Authentication errors are at minimum 'high' severity
      """
      ...
  ```

  ```typescript TypeScript theme={null}
  type Severity = 'critical' | 'high' | 'medium' | 'low';

  async function categorizeSeverity(
    errorMessage: string,
    stackTrace: string
  ): Promise<Severity> {
    return agentic<Severity>(
      `Categorize error severity.

      Constraints:
      - Return 'critical' if: data loss, security breach, system crash
      - Return 'high' if: feature unusable, affects multiple users
      - Return 'medium' if: degraded performance, workaround available
      - Return 'low' if: cosmetic issue, minimal impact

      Edge cases:
      - If stackTrace is empty, base decision on errorMessage alone
      - Database errors are at minimum 'high' severity
      - Authentication errors are at minimum 'high' severity`,
      { errorMessage, stackTrace }
    );
  }
  ```
</CodeGroup>

For parsing or extraction tasks, define what constitutes valid input and what to return when inputs are missing or malformed:

<CodeGroup>
  ```python Python theme={null}
  @agentic()
  async def parse_date_range(text: str) -> tuple[str, str] | None:
      """
      Extract start and end dates from natural language.

      Return format: (start_date, end_date) as YYYY-MM-DD strings

      Constraints:
      - Start date must be before or equal to end date
      - Return None if no date range found
      - Return None if only one date found (need both)

      Edge cases:
      - "last week" → Monday to Sunday of previous week
      - "Q1 2024" → 2024-01-01 to 2024-03-31
      - Relative dates use today's date as reference
      """
      ...
  ```

  ```typescript TypeScript theme={null}
  async function parseDateRange(text: string): Promise<[string, string] | null> {
    return agentic<[string, string] | null>(
      `Extract start and end dates from natural language.

      Return format: [startDate, endDate] as YYYY-MM-DD strings

      Constraints:
      - Start date must be before or equal to end date
      - Return null if no date range found
      - Return null if only one date found (need both)

      Edge cases:
      - "last week" → Monday to Sunday of previous week
      - "Q1 2024" → 2024-01-01 to 2024-03-31
      - Relative dates use today's date as reference`,
      { text }
    );
  }
  ```
</CodeGroup>

**For multi-step validation workflows**, use an agent that progressively checks and adapts based on what it discovers. The agent remembers previous findings when deciding next steps:

<CodeGroup>
  ```python Python theme={null}
  from agentica import spawn
  from typing import Literal

  agent = await spawn(premise="You are a security validator for user queries")

  # Step 1: Agent analyzes input for safety
  safety = await agent.call(
      Literal['safe', 'sql_injection', 'invalid_chars'],
      "Classify this user input for security issues",
      user_input=untrusted_input
  )

  # Step 2: Based on what agent found, take different actions
  if safety == 'safe':
      # Agent remembers the input it just analyzed
      normalized = await agent.call(
          str,
          "Normalize the input you just validated (lowercase, trim, remove extra spaces)"
      )
      return normalized
  elif safety == 'sql_injection':
      # Agent remembers what SQL patterns it detected
      details = await agent.call(
          str,
          "Explain which SQL patterns you detected and why they're dangerous"
      )
      log_security_violation(details)
      raise SecurityError(details)
  else:
      # Agent remembers the invalid characters it found
      suggestion = await agent.call(
          str,
          "Suggest what the user should change about their input"
      )
      return f"Invalid input. {suggestion}"
  ```

  ```typescript TypeScript theme={null}
  import { spawn } from '@symbolica/agentica';

  const agent = await spawn({ premise: "You are a security validator for user queries" });

  // Step 1: Agent analyzes input for safety
  const safety = await agent.call<'safe' | 'sql_injection' | 'invalid_chars'>(
    "Classify this user input for security issues",
    { userInput: untrustedInput }
  );

  // Step 2: Based on what agent found, take different actions
  if (safety === 'safe') {
    // Agent remembers the input it just analyzed
    const normalized = await agent.call<string>(
      "Normalize the input you just validated (lowercase, trim, remove extra spaces)"
    );
    return normalized;
  } else if (safety === 'sql_injection') {
    // Agent remembers what SQL patterns it detected
    const details = await agent.call<string>(
      "Explain which SQL patterns you detected and why they're dangerous"
    );
    logSecurityViolation(details);
    throw new Error(details);
  } else {
    // Agent remembers the invalid characters it found
    const suggestion = await agent.call<string>(
      "Suggest what the user should change about their input"
    );
    return `Invalid input. ${suggestion}`;
  }
  ```
</CodeGroup>

## Agents

For agents, the Agentica SDK formats an initial **system role message using the provided `premise`** on instantiation.
Any subsequent invocation or call of an agent formats a **user role message using the provided `task`**.

The `premise` should provide additional context on the **agent's overall purpose or goal** over its lifetime, while the `task` should provide information about its **immediate goal**, linked to the specified return type.

### Custom prompts

Both the Python and TypeScript SDK offer the ability to **provide an entirely custom system role message for agents** via the `system` argument in `spawn`.
If `system` is provided instead of `premise`, then **`system` will be the exact system role message** on instantiation and **`task` will be the exact user role message** on invocation of the agent, without any formatting.

<CodeGroup>
  ```python Python wrap theme={null}
  agent = await spawn(
      system="""
      You are a data extraction API. You receive documents and schemas.
      You MUST return valid JSON matching the schema. Never include explanations,
      preambles, or markdown formatting. Just the JSON object.
      """, # This will be the prompt provided to the model under the role system
      model="anthropic/claude-opus-4.6"
  )
  ```

  ```typescript TypeScript wrap theme={null}
  // For agents that must return ONLY structured data
  const agent = await spawn({
      system: `You are a data extraction API. You receive documents and schemas.
      You MUST return valid JSON matching the schema. Never include explanations,
      preambles, or markdown formatting. Just the JSON object.`, // This will be the prompt provided to the model under the role system
      model: "anthropic/claude-opus-4.6" 
  });
  ```
</CodeGroup>

### Templating variables

To **include information about the environment and the agent's capabilities** in your custom `system` prompts and `task`, a number of **templatable "explainer" variables** are exported in the Agentica SDK.
These are formatted using the `template` function and these variables slightly differ per model.

<Tip>
  For more information on `template` see [here for Python](/references/python/templating) and [here for TypeScript](/references/ts/templating).

  For precise values of these variables see [here](/prompting/agent#templating-variables).
</Tip>

<Warning>
  Note that `template` is not supported for an agent `premise` for both the Python and TypeScript SDKs.
</Warning>

<CodeGroup>
  ```python Python wrap theme={null}
  from agentica import template

  SYSTEM = template("""
  You are a special agent.
  You have access to a REPL.

  {{OBJECTIVES}} 
  """) # The OBJECTIVES variable outlines the objectives and constraints of the agent w.r.t the REPL

  agent = await spawn(system=SYSTEM)
  result = await agent.call(
    float,
    template("Give me the square root of 16. Return {{RETURN_TYPE}}."), # This variable will correspond to `float`
  )
  print(result)
  ```

  ```typescript TypeScript wrap theme={null}
  import { template } from '@symbolica/agentica/template';

  SYSTEM = template`
  You are a special agent.
  You have access to a REPL.

  {{OBJECTIVES}} 
  `; // The OBJECTIVES variable outlines the objectives and constraints of the agent w.r.t the REPL

  const agent = await spawn({ system: SYSTEM });
  const result = await agent.call<number>(
    template`Give me the square root of 16. Return {{RETURN_TYPE}}.`, // This variable will correspond to `number`
  );
  console.log(result);
  ```
</CodeGroup>

## Agentic functions

### Templating variables

To **include information about the environment and the agent's capabilities** when writing an agentic function, a number of **templatable "explainer" variables** are exported in the Agentica SDK.
These are formatted using the `template` function and these variables slightly differ per model.

<Tip>
  For more information on `template` see [here for Python](/references/python/templating) and [here for TypeScript](/references/ts/templating).

  For precise values of these variables see [here](/prompting/agent#templating-variables).
</Tip>

<Warning>
  Note that `template` is not supported for doc-strings of agentic functions for the Python SDK.
</Warning>

<CodeGroup>
  ```typescript TypeScript wrap theme={null}
  import { agentic } from '@symbolica/agentica';
  import { template } from '@symbolica/agentica/template';

  async function mathematician(problem: string): Promise<number> {
    return await agentic(
      template`
  You are a mathematician.
  You have access to a REPL.

  {{OBJECTIVES}}
      `, // The OBJECTIVES variable outlines the objectives and constraints of the agent w.r.t the REPL
      { problem }
    );
  }

  const result = await mathematician(`Give me the square root of 16.`)
  console.log(result);
  ```
</CodeGroup>
