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

# Getting the most out of agents

> Practical guidance on instruction writing, mode selection, knowledge scoping, tool choice, and cost/latency trade-offs.

This page collects practical patterns for building reliable, cost-effective agents. Read [Getting started with Agents](/api-reference/agents/agents) first if you haven't set up an agent yet.

## Write effective system instructions

The three instruction fields serve distinct purposes — using them well is the single highest-leverage thing you can do for quality:

| Field             | Use it for                                                                                                       |
| ----------------- | ---------------------------------------------------------------------------------------------------------------- |
| `system_prompt`   | **What** the agent does: its role, scope, and behavioral constraints.                                            |
| `custom_prompt`   | **How** it responds: tone, format, length, and style.                                                            |
| `planning_prompt` | **How** it approaches complex work: task decomposition, tool-use sequencing, or domain-specific reasoning steps. |

### Be specific about role and scope

Vague instructions produce inconsistent results. Give the agent a clear role and list what it should and should not do.

<CodeGroup>
  ```python Python theme={null}
  # Vague — the agent will guess
  agent = client.agents.create(
      name="HR Assistant",
      system_prompt="Help employees with HR questions.",
  )

  # Better — role, scope, and a hard constraint are explicit
  agent = client.agents.create(
      name="HR Assistant",
      system_prompt=(
          "You are an HR assistant for Acme Corp employees. "
          "Answer questions about benefits, leave policies, and onboarding. "
          "Do not provide legal advice or discuss compensation for specific individuals."
      ),
      custom_prompt="Use plain language. Keep answers under three paragraphs unless the user asks for more detail.",
  )
  ```

  ```javascript JavaScript theme={null}
  // Vague — the agent will guess
  const agentVague = await client.agents.create({
    name: 'HR Assistant',
    system_prompt: 'Help employees with HR questions.',
  });

  // Better — role, scope, and a hard constraint are explicit
  const agent = await client.agents.create({
    name: 'HR Assistant',
    system_prompt:
      'You are an HR assistant for Acme Corp employees. ' +
      'Answer questions about benefits, leave policies, and onboarding. ' +
      'Do not provide legal advice or discuss compensation for specific individuals.',
    custom_prompt:
      'Use plain language. Keep answers under three paragraphs unless the user asks for more detail.',
  });
  ```
</CodeGroup>

### Use `planning_prompt` for multi-step work

For agents that orchestrate complex tasks — generating reports, extracting data across sources, or running multi-step workflows — `planning_prompt` tells the agent how to think before it acts:

<CodeGroup>
  ```python Python theme={null}
  agent = client.agents.create(
      name="Data Analyst",
      system_prompt="Analyze datasets and produce summaries with charts.",
      planning_prompt=(
          "Before answering, identify which datasets are relevant, then outline your analysis steps. "
          "Run `data_analysis` on each dataset before synthesizing results. "
          "Always create a chart if the answer is best communicated visually."
      ),
  )
  ```

  ```javascript JavaScript theme={null}
  const agent = await client.agents.create({
    name: 'Data Analyst',
    system_prompt: 'Analyze datasets and produce summaries with charts.',
    planning_prompt:
      'Before answering, identify which datasets are relevant, then outline your analysis steps. ' +
      'Run `data_analysis` on each dataset before synthesizing results. ' +
      'Always create a chart if the answer is best communicated visually.',
  });
  ```
</CodeGroup>

<Tip>
  Iterate instructions the same way you iterate code: start minimal, run real prompts, and refine based on failures. The [generate → claim → create](/api-reference/agents/agents#generate-an-agent-from-natural-language) flow is useful for getting a first draft quickly.
</Tip>

## Choose the right mode

The mode controls how much planning and tool use happens for each turn. Pick the lightest mode that meets your needs — heavier modes take longer and cost more.

<Note>
  `magpie-2.5-flash` is deprecated and being withdrawn. Do not use it for new agents. For Ask behavior, use `chat_mode: "llm_router"`; for retrieval-focused workflows, use `magpie-1.1-flash`.
</Note>

| Situation                                                     | Recommended approach                                                                                                |
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| Need full multi-step reasoning and tools                      | Execute tier: omit `agent_model` (defaults to `magpie-2.0`), or set `agent_model: "magpie-2.5"` for the latest beta |
| Need fast answers from a knowledge base                       | Extended tier: `config.agent_model: "magpie-1.1-flash"` — `semantic_search` only                                    |
| Need tool-free LLM responses (structured output, simple Q\&A) | `config.agent_model: "llm-only"`                                                                                    |
| Reproducing in-app Ask behavior                               | `chat_mode: "llm_router"` (a routing mode, not a model)                                                             |

<CodeGroup>
  ```python Python theme={null}
  # Execute (default) — multi-step reasoning and all tools
  response = client.converse(
      prompt="Analyze last quarter's sales and flag any anomalies.",
      agent_id=agent.id,
      config={"agent_model": "magpie-2.0"},
  )

  # Extended — fast RAG, semantic_search only
  response = client.converse(
      prompt="What does the handbook say about parental leave?",
      agent_id=agent.id,
      config={
          "agent_model": "magpie-1.1-flash",
          "tools": ["semantic_search"],
      },
  )

  # Direct LLM — no tools, lowest latency
  response = client.converse(
      prompt="Summarize this paragraph in one sentence.",
      config={"agent_model": "llm-only"},
  )
  ```

  ```javascript JavaScript theme={null}
  // Execute (default) — multi-step reasoning and all tools
  const executeResponse = await client.converse({
    prompt: 'Analyze last quarter\'s sales and flag any anomalies.',
    agent_id: agent.id,
    config: { agent_model: 'magpie-2.0' },
  });

  // Extended — fast RAG, semantic_search only
  const extendedResponse = await client.converse({
    prompt: 'What does the handbook say about parental leave?',
    agent_id: agent.id,
    config: {
      agent_model: 'magpie-1.1-flash',
      tools: ['semantic_search'],
    },
  });

  // Direct LLM — no tools, lowest latency
  const llmResponse = await client.converse({
    prompt: 'Summarize this paragraph in one sentence.',
    config: { agent_model: 'llm-only' },
  });
  ```
</CodeGroup>

See [Converse modes](/api-reference/converse/modes) for the full mapping between `chat_mode`, `config.agent_model`, in-app labels, and tool availability.

## Scope knowledge for predictable behavior

By default an agent can reach **all knowledge** your organization has access to. This is convenient for exploration but problematic in production: the agent may pull in unrelated content, or expose knowledge that shouldn't inform the answer.

Set `corpus` explicitly to lock down what the agent reads.

<CodeGroup>
  ```python Python theme={null}
  # Without corpus — agent can reach all knowledge (unpredictable blast radius)
  agent = client.agents.create(
      name="Support Assistant",
      system_prompt="Answer customer support questions.",
  )

  # With corpus — agent reads only the sources you specify
  agent = client.agents.create(
      name="Support Assistant",
      system_prompt="Answer customer support questions.",
      corpus=[
          {"type": "knowledge", "knowledge_id": "kn_support_docs"},
          {"type": "knowledge", "knowledge_id": "kn_product_faq"},
      ],
  )
  ```

  ```javascript JavaScript theme={null}
  // Without corpus — agent can reach all knowledge (unpredictable blast radius)
  const agentBroad = await client.agents.create({
    name: 'Support Assistant',
    system_prompt: 'Answer customer support questions.',
  });

  // With corpus — agent reads only the sources you specify
  const agent = await client.agents.create({
    name: 'Support Assistant',
    system_prompt: 'Answer customer support questions.',
    corpus: [
      { type: 'knowledge', knowledge_id: 'kn_support_docs' },
      { type: 'knowledge', knowledge_id: 'kn_product_faq' },
    ],
  });
  ```
</CodeGroup>

You can also scope a single Converse turn without changing the stored agent by passing `config.corpus` on the request:

<CodeGroup>
  ```python Python theme={null}
  response = client.converse(
      prompt="Summarize only the Q4 policy updates.",
      agent_id=agent.id,
      config={"corpus": [{"type": "knowledge", "knowledge_id": "kn_q4_policies"}]},
  )
  ```

  ```javascript JavaScript theme={null}
  const response = await client.converse({
    prompt: 'Summarize only the Q4 policy updates.',
    agent_id: agent.id,
    config: { corpus: [{ type: 'knowledge', knowledge_id: 'kn_q4_policies' }] },
  });
  ```
</CodeGroup>

<Tip>
  Each corpus item is either `{ "type": "knowledge", "knowledge_id": "kn_…" }` or `{ "type": "page", "page_id": "page_…" }`. Mixing both types in the same corpus is allowed. See [Knowledge and corpus](/api-reference/converse/knowledge-and-corpus) for more details.
</Tip>

## Select tools with least privilege

Giving an agent every tool makes it flexible but also increases the risk of side effects (writing data when the agent should only read) and can add latency from unnecessary tool-selection overhead.

**Start with the minimum tools needed and add more only when required.**

| Tool category         | Tools                                                                                           | When to include                                  |
| --------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| Knowledge             | `semantic_search`, `data_analysis`, `schema_info`, `table_info`, `agent_memory`, `charts`       | Read-only agents: knowledge lookup and analysis  |
| Data actions          | `create_dataset`, `data_classification`, `data_extraction`, `image_detection`, `pdf_extraction` | When the agent needs to create or transform data |
| Web                   | `web_search`, `fetch_url`, `company_prospect_researcher`, `people_prospect_researcher`          | When the agent needs live web information        |
| Calendar / scheduling | `calendar`, `schedule_recurring_message_tool`                                                   | Only for agents that explicitly manage time      |

### Use `disabled_tools` for fine-grained control

`disabled_tools` is applied *after* the `tools` list — useful when you want most of the default set but need to block specific tools:

<CodeGroup>
  ```python Python theme={null}
  # Allow the default tool set, but prevent write operations
  agent = client.agents.create(
      name="Read-Only Analyst",
      system_prompt="Answer data questions. Do not create or modify datasets.",
      disabled_tools=["create_dataset"],
  )
  ```

  ```javascript JavaScript theme={null}
  // Allow the default tool set, but prevent write operations
  const agent = await client.agents.create({
    name: 'Read-Only Analyst',
    system_prompt: 'Answer data questions. Do not create or modify datasets.',
    disabled_tools: ['create_dataset'],
  });
  ```
</CodeGroup>

<Note>
  `magpie-1.1-flash` (Extended tier) only supports `semantic_search`. `llm-only` supports no tools. Specifying unsupported tools for these models will cause the request to be rejected.
</Note>

## Use structured outputs for integrations

When Converse is part of a pipeline — a webhook handler, a data-processing job, or a typed API — use `text.format` to guarantee the response matches your schema. This works for every mode and agent.

<CodeGroup>
  ```python Python theme={null}
  import json

  response = client.converse(
      prompt="Extract the contract start date and total value from this document.",
      agent_id=agent.id,
      text={
          "format": {
              "type": "object",
              "properties": {
                  "start_date": {"type": "string", "description": "ISO 8601 date"},
                  "total_value": {"type": "number"},
                  "currency": {"type": "string"},
              },
              "required": ["start_date", "total_value", "currency"],
              "additionalProperties": False,
          }
      },
  )

  data = json.loads(response.content[0].text)
  print(data["start_date"], data["total_value"])
  ```

  ```javascript JavaScript theme={null}
  const response = await client.converse({
    prompt: 'Extract the contract start date and total value from this document.',
    agent_id: agent.id,
    text: {
      format: {
        type: 'object',
        properties: {
          start_date: { type: 'string', description: 'ISO 8601 date' },
          total_value: { type: 'number' },
          currency: { type: 'string' },
        },
        required: ['start_date', 'total_value', 'currency'],
        additionalProperties: false,
      },
    },
  });

  const data = JSON.parse(response.content[0].text);
  console.log(data.start_date, data.total_value);
  ```
</CodeGroup>

Schema design tips:

* Keep schemas flat where possible — deeply nested schemas are harder to validate and produce more hallucination surface.
* Mark only the fields you always need as `required`. Optional fields reduce failures on partial data.
* Use `additionalProperties: false` to prevent the model from adding undocumented keys.

See [Structured outputs](/api-reference/converse/structured-outputs) for the full reference.

## Iterate faster with the generate → claim → create flow

When starting a new agent, use `agents.generate` to get a first draft of instructions and tool selection from a natural-language description, then refine by hand.

<CodeGroup>
  ```python Python theme={null}
  # Describe what you need — no auth required, rate-limited to 5 requests/day per IP
  generated = client.agents.generate(
      prompt="An agent that reviews construction RFIs and flags missing information.",
  )

  # Claim the template to retrieve its configuration
  template = client.agents.claim(claim_token=generated.claim_token)

  # Review and refine before creating
  agent = client.agents.create(
      name=template.title,
      system_prompt=template.config.prompt,         # Refine this
      custom_prompt=template.config.custom_prompt,  # Refine this
      tools=[t.tool for t in template.config.tools],
      corpus=[{"type": "knowledge", "knowledge_id": "kn_rfi_docs"}],  # Add explicit scoping
  )
  ```

  ```javascript JavaScript theme={null}
  // Describe what you need — no auth required, rate-limited to 5 requests/day per IP
  const generated = await client.agents.generate({
    prompt: 'An agent that reviews construction RFIs and flags missing information.',
  });

  // Claim the template to retrieve its configuration
  const template = await client.agents.claim({ claim_token: generated.claim_token });

  // Review and refine before creating
  const agent = await client.agents.create({
    name: template.title,
    system_prompt: template.config.prompt,         // Refine this
    custom_prompt: template.config.custom_prompt,  // Refine this
    tools: template.config.tools.map((t) => t.tool),
    corpus: [{ type: 'knowledge', knowledge_id: 'kn_rfi_docs' }], // Add explicit scoping
  });
  ```
</CodeGroup>

<Note>
  The `claim_token` expires after 7 days. The claim step retrieves the template — it does **not** create an agent. You still need to call `agents.create` to persist it.
</Note>

After creating, use `agents.update` to iterate on instructions without destroying and re-creating the agent:

<CodeGroup>
  ```python Python theme={null}
  client.agents.update(
      agent.id,
      system_prompt="Refined instructions after testing...",
      planning_prompt="Updated planning strategy...",
  )
  ```

  ```javascript JavaScript theme={null}
  await client.agents.update(agent.id, {
    system_prompt: 'Refined instructions after testing...',
    planning_prompt: 'Updated planning strategy...',
  });
  ```
</CodeGroup>

## Cost and latency guidance

Mode choice is the primary lever for both cost and latency:

The table below covers the currently recommended models. `magpie-2.5-flash` is deprecated and being withdrawn, so it is intentionally omitted.

| Model              | Latency     | Tools                  | Best for                                                             |
| ------------------ | ----------- | ---------------------- | -------------------------------------------------------------------- |
| `llm-only`         | Lowest      | None                   | Simple Q\&A, classification, structured extraction with no retrieval |
| `magpie-1.1-flash` | Low         | `semantic_search` only | Fast knowledge-base lookups and RAG summarization                    |
| `magpie-2.0`       | Medium–High | All                    | Multi-step reasoning, data analysis, actions                         |
| `magpie-2.5`       | Medium–High | All                    | Latest Execute-tier capabilities (beta)                              |

See [Converse modes](/api-reference/converse/modes) for the authoritative tier table.

### Reduce streaming overhead

When streaming, set `include_steps: false` to suppress intermediate tool and reasoning events. This reduces event volume and is the right default for end-user-facing UIs that only need to show the final answer:

<CodeGroup>
  ```python Python theme={null}
  response = client.converse(
      prompt="Summarize the latest report.",
      agent_id=agent.id,
      stream=True,
      include_steps=False,
  )

  for event in response:
      if event.event == "delta":
          print(event.delta.text, end="", flush=True)
  ```

  ```javascript JavaScript theme={null}
  const response = await client.converse({
    prompt: 'Summarize the latest report.',
    agent_id: agent.id,
    stream: true,
    include_steps: false,
  });

  for await (const event of response) {
    if (event.event === 'delta') {
      process.stdout.write(event.data.delta.text);
    }
  }
  ```
</CodeGroup>

<Tip>
  Use `stream: true` for any task that may take several seconds — it gives end-users visible progress instead of a silent wait, even if you're only interested in the final `end` event. See [Streaming](/api-reference/converse/streaming) for the full event shape.
</Tip>

### Other latency tips

* **Narrow `corpus`** — a tightly scoped corpus means the retrieval step searches less, returning results faster.
* **Narrow `tools`** — fewer tools means less overhead for the agent to decide which to call.
* **Cache `conversation_id`** — re-using a `conversation_id` gives the agent conversation history without re-sending it, keeping prompt size bounded over long sessions.

## Next steps

* [Getting started with Agents](/api-reference/agents/agents) — create and configure agents from scratch.
* [Getting started with Converse](/api-reference/converse/converse-getting-started) — the endpoint that runs them.
* [Converse modes](/api-reference/converse/modes) — full mode and model reference.
* [Knowledge and corpus](/api-reference/converse/knowledge-and-corpus) — corpus configuration deep-dive.
* [Structured outputs](/api-reference/converse/structured-outputs) — schema design and response parsing.
* [Streaming](/api-reference/converse/streaming) — full SSE event reference.
* [Agents API reference](/api-reference/agents/create-agent) — every field and endpoint.
