> ## 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.

# CORS and credentials in AgentOS

> How AgentOS handles wildcard origins and credentialed browser requests

AgentOS turns off credentialed CORS when you allow every origin, so other websites can't use your users' cookies to call your agents.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Req[🌐 Browser request] --> CORS{🛡️ cors_origins has '*'?}
    CORS -->|Yes| Drop[🚫 Credentials not allowed]
    CORS -->|No| Keep[✅ Credentials allowed]

    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef decision fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef ok fill:#10B981,stroke:#7C90A0,color:#fff
    classDef drop fill:#189AB4,stroke:#7C90A0,color:#fff

    class Req agent
    class CORS decision
    class Keep ok
    class Drop drop
```

## Quick Start

**1. Public endpoint, no cookies**

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

agent = Agent(instructions="Be helpful")

AgentOS(
    agents=[agent],
    cors_origins=["*"],  # Any site can call it. Credentials are dropped.
).serve()
```

**2. Browser app with cookies**

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

agent = Agent(instructions="Be helpful")

AgentOS(
    agents=[agent],
    cors_origins=["https://app.example.com"],  # Credentialed CORS works.
).serve()
```

***

## How It Works

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant Browser
    participant AgentOS

    Browser->>AgentOS: fetch(..., credentials: "include")
    alt cors_origins contains "*"
        AgentOS-->>Browser: No Access-Control-Allow-Credentials
        Note over Browser: Browser blocks the response
    else explicit origin matches
        AgentOS-->>Browser: Allow-Origin: https://app.example.com<br/>Allow-Credentials: true
        Note over Browser: Response delivered
    end
```

| `cors_origins` | Credentials (cookies, credentialed `fetch`) |
| - | - |
| `[]` (default) | No cross-origin access |
| `["*"]` | Not allowed |
| `["https://app.example.com"]` | Allowed for that origin |
| `["https://app.example.com", "*"]` | Not allowed — any `"*"` turns credentials off |

The same rule applies to the async jobs server when you pass `cors_origins` to `praisonai.jobs.server.create_app`.

> [!NOTE]
>
> The `Authorization` header still works with `["*"]` when your client sends it without `credentials: "include"` — for example, a bearer token from your API key.

***

## Why

With a `"*"` origin and credentials both enabled, Starlette's CORS middleware echoes the caller's `Origin` header back when a cookie is present. Any website could then make logged-in requests to your deployment. Browsers forbid `*` with credentials for this reason, and AgentOS enforces the same rule on the server.

***

## Best Practices

> [accordion] List exact frontend origins in production
>
> Use `cors_origins=["https://app.example.com"]` instead of `["*"]` for any deployed frontend.

> [accordion] Never mix "\*" with other origins
>
> One `"*"` entry turns credentials off for the whole list.

> [accordion] Check browser clients after upgrading
>
> If cookie-based browser calls stopped working after an upgrade, you were relying on `["*"]` with credentials. Switch to an explicit origin list.

***

## Related

> [card] [AgentOS](https://praison.ai/docs/concepts/agentos.md)
>
> AgentOS configuration and lifecycle

> [card] [Async Jobs](https://praison.ai/docs/features/async-jobs.md)
>
> Jobs server that follows the same CORS rule


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