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

# Model Parameter

> One model parameter, one canonical name — model=

`model=` is the canonical name for the model on every agent class; `llm=` is a deprecated alias for it.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "One parameter, one name"
        M[✅ model=&quot;gpt-4o&quot;] --> OK[🤖 Agent runs]
        L[⚠️ llm=&quot;gpt-4o&quot;] --> OK
        B[❌ llm= and model=] --> Err[🚫 TypeError]
    end

    classDef canonical fill:#10B981,stroke:#7C90A0,color:#fff
    classDef deprecated fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef both fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef agent fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef error fill:#6366F1,stroke:#7C90A0,color:#fff

    class M canonical
    class L deprecated
    class B both
    class OK agent
    class Err error
```

## Quick Start

<Steps>
  <Step title="Use the canonical name">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent

    agent = Agent(
        instructions="Summarise the given article in three bullets.",
        model="gpt-4o",
    )

    agent.start("<article text>")
    ```
  </Step>

  <Step title="The deprecated alias still works">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent

    agent = Agent(
        instructions="Summarise the given article.",
        llm="gpt-4o",
    )
    ```

    <Note>
      `llm=` still works but emits a `DeprecationWarning`. Move to `model=` at your convenience.
    </Note>
  </Step>

  <Step title="Passing both is refused">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent

    # ❌ Passing both is refused
    Agent(instructions="…", llm="gpt-4o", model="gpt-3.5-turbo")
    # TypeError: Agent() received both llm= and model=. They are the same
    #   parameter, so passing both is ambiguous. Pass only one; model= is
    #   the canonical name (llm= is a deprecated alias).
    ```
  </Step>
</Steps>

***

## How It Works

Every agent class routes `llm=` and `model=` through one resolver so the rule is identical everywhere.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Start{Both llm= and model= set?} -->|Yes| Raise[🚫 raise TypeError]
    Start -->|No| Pick[Pick the non-None one]
    Pick --> Wrap{LLMConfig on a container<br/>or media/specialist agent?}
    Wrap -->|Yes — AgentTeam, AgentFlow,<br/>or a media/specialist agent| Unwrap[Unwrap to the bare .model string]
    Wrap -->|No — bare Agent| Use[Store the LLMConfig as-is]

    classDef question fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef error fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef action fill:#10B981,stroke:#7C90A0,color:#fff

    class Start,Wrap question
    class Raise error
    class Pick,Unwrap,Use action
```

| Call | Result |
| - | - |
| `Agent(model="gpt-4o")` | ✅ Canonical. Preferred everywhere. |
| `Agent(llm="gpt-4o")` | ⚠️ Deprecated alias. Works, emits a `DeprecationWarning`. |
| `Agent(llm="gpt-4o", model="gpt-3.5-turbo")` | ❌ `TypeError` — same parameter, so passing both is ambiguous. |
| `Agent(model=LLMConfig(model="gpt-4o", …))` | ✅ Accepted. Stored as the `LLMConfig` object (bare `Agent` uses it directly). |
| `VisionAgent(model=LLMConfig(model="gpt-4o", …))` (or any media/specialist agent) | ✅ Accepted. Unwrapped to the bare `"gpt-4o"` string; `base_url` / `api_key` on the config are dropped. |
| `AgentTeam(model=LLMConfig(model="gpt-4o", …))` / `AgentFlow(model=LLMConfig(model="gpt-4o", …))` | ✅ Accepted. Unwrapped to the bare `"gpt-4o"` string before it fills in members. `base_url` / `api_key` / `fallback_models` on the config are dropped for containers today. |

***

## Where It Applies

The `llm=` / `model=` pair resolves the same way on every class below.

| Class | Accepts `model=` | Accepts `llm=` (deprecated) |
| - | :-: | :-: |
| `Agent` | ✅ | ✅ |
| `AgentTeam` | ✅ | ✅ |
| `AgentFlow` | ✅ | ✅ |
| `VisionAgent` | ✅ | ✅ |
| `AudioAgent` | ✅ | ✅ |
| `OCRAgent` | ✅ | ✅ |
| `VideoAgent` | ✅ | ✅ |
| `EmbeddingAgent` | ✅ | ✅ |
| `ImageAgent` | ✅ | ✅ |
| `ContextAgent` | ✅ | ✅ |
| `CodeAgent` | ✅ | ✅ |
| `RealtimeAgent` | ✅ | ✅ |

<Note>
  `manager_llm=` on `AgentTeam` / `AgentFlow` is **separate** and unchanged — it is the hierarchical manager's model and never touches the members.
</Note>

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, AgentTeam, Task

# Default model for members that did not name one themselves
team = AgentTeam(
    agents=[Agent(instructions="Researcher"), Agent(instructions="Writer")],
    tasks=[Task(description="Write a two-paragraph brief on quantum sensing.")],
    model="gpt-4o-mini",
)

team.start()
```

***

## Custom LLM objects

Pass any object with a `get_response` or `get_response_async` method to `llm=` and the agent uses it as its backend instead of the OpenAI default. The tool loop calls `llm_instance.get_response(**kwargs)` (or its async twin), so those are the two surfaces the agent detects on.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

class MyBackend:
    model = "my-backend"
    def get_response(self, prompt, **kwargs):
        return "answer from my backend"

agent = Agent(instructions="Use my backend.", llm=MyBackend())
agent.start("hello")   # routed to MyBackend, not OpenAI
```

An async-only backend works too — expose `get_response_async` and the async tool loop drives it. Either method alone is enough; you do not need both.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

class MyAsyncBackend:
    model = "my-async-backend"
    async def get_response_async(self, prompt, **kwargs):
        return "answer from my async backend"

agent = Agent(instructions="Use my async backend.", llm=MyAsyncBackend())
agent.start("hello")
```

The agent detects on `get_response` and `get_response_async`, so any backend exposing either works — including the `ScriptedModel` test double from [Offline Testing](/docs/features/offline-testing).

<Note>
  **What is not adopted.** `praisonaiagents/llm/protocols.py` also defines `LLMProviderProtocol` (`chat` / `achat`) and `UnifiedLLMProtocol` (`chat_completion` / `achat_completion`). Those are provider-side protocols for other subsystems — the `Agent` tool loop drives `get_response` / `get_response_async` only. A backend exposing only `chat` / `chat_completion` is not picked up by `Agent(llm=<obj>)`; wrap it in a small class that exposes `get_response`, or use it as a plain provider.
</Note>

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Start["🧩 Agent(llm=&lt;object&gt;)"] --> Q1{Has get_response<br/>or get_response_async?}
    Q1 -->|Yes| Adopt["✅ Adopted as backend<br/>_using_custom_llm = True"]
    Q1 -->|No| Q2{Only chat / achat /<br/>chat_completion / achat_completion?}
    Q2 -->|Yes| Skip["⚠️ Not adopted<br/>wrap it to expose get_response"]
    Q2 -->|No| Default["❌ Falls through to string/dict path"]

    classDef entry fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef gate fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef ok fill:#10B981,stroke:#7C90A0,color:#fff
    classDef warn fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef bad fill:#6366F1,stroke:#7C90A0,color:#fff

    class Start entry
    class Q1,Q2 gate
    class Adopt ok
    class Skip warn
    class Default bad
```

<Warning>
  **Before PraisonAI [#4929](https://github.com/MervinPraison/PraisonAI/pull/4929)**, passing your own model object fell through every branch to the plain OpenAI path: `self.llm` became the object itself and `_using_custom_llm` stayed `False`, so every turn went to OpenAI under a model name that was really a `repr()`. [#4929](https://github.com/MervinPraison/PraisonAI/pull/4929) adopted `get_response`-shaped backends; [#4959](https://github.com/MervinPraison/PraisonAI/pull/4959) refined the detection to `get_response` and `get_response_async` and pinned it to the surface the tool loop can actually drive.
</Warning>

***

## Migration

<AccordionGroup>
  <Accordion title="I use llm= in every example">
    No code change is required — `llm=` still works. Move to `model=` at your convenience; it is the canonical name.
  </Accordion>

  <Accordion title="I pass both llm= and model= today">
    Pick one. `model=` is the canonical name. Passing both now raises `TypeError` because the two are the same parameter and guessing a winner could change which vendor is billed.
  </Accordion>

  <Accordion title="I pass an LLMConfig to a specialised agent">
    On `VisionAgent`, `AudioAgent`, `OCRAgent`, `VideoAgent`, `EmbeddingAgent`, `CodeAgent`, `RealtimeAgent`, `ImageAgent`, and `ContextAgent` you no longer need to unwrap an `LLMConfig` yourself. The class stores its `.model` string and keeps its own `base_url=` / `api_key=`.
  </Accordion>

  <Accordion title="I pass an LLMConfig to a container (AgentTeam / AgentFlow)">
    `AgentTeam(llm=LLMConfig(...))` and `AgentFlow(llm=LLMConfig(...))` unwrap the config to its `.model` string before filling in members. Before this fix, the raw `LLMConfig` was pushed into every member and each member's `chat()` returned `None` silently. `base_url`, `api_key`, `auth`, and `fallback_models` on the config are dropped for containers today — pin those on the individual member `Agent`(s) if you need them.
  </Accordion>

  <Accordion title="I use CodeAgent(llm=…), RealtimeAgent(llm=…), AgentTeam(llm=…), or AgentFlow(llm=…)">
    Those four now also accept `model=` (canonical). The alias `llm=` still works.
  </Accordion>
</AccordionGroup>

<Warning>
  Passing `LLMConfig(...)` to `AgentTeam` or `AgentFlow` today keeps only `.model` — `base_url`, `api_key`, `auth`, and `fallback_models` are dropped. Pin those on the individual member `Agent`(s) when you need a custom endpoint, alternate credentials, or a fallback chain per member.
</Warning>

***

## Related

<CardGroup cols={2}>
  <Card title="LLM Config" icon="sliders" href="/docs/features/llm-config">
    Pass an `LLMConfig` object to `model=` for `base_url`, `api_key`, and fallbacks.
  </Card>

  <Card title="Legacy Agent Parameters" icon="arrow-right-arrow-left" href="/docs/features/agent-legacy-params">
    Other deprecated `Agent()` parameters and their replacements.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.