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

# Quick Start

Qoder Agent SDK lets you call Qoder AI capabilities from Python — read/write files, search code, execute commands, and more — embedding an AI Agent into your application or script with just a few lines of code.

<div id="prerequisites" />

## Prerequisites

* Python 3.10+

<div id="install" />

## Install

```bash theme={null}
pip install qoder-agent-sdk
```

<div id="authentication" />

## Authentication

The SDK authenticates via a Personal Access Token (PAT), ideal for scripts, CI pipelines, and third-party integration scenarios.

Generate a PAT at [qoder.com/account/integrations](https://qoder.com/account/integrations) (copy it immediately — the value cannot be retrieved again after the page is closed). For full steps, custom environment variables, and reusing the local `qodercli` login session, see [SDK Authentication](/en/cli/sdk/python/authentication).

Once you have a PAT, set the environment variable first:

```bash theme={null}
export QODER_PERSONAL_ACCESS_TOKEN="<your-qoder-personal-access-token>"
python agent.py
```

Then configure authentication using `access_token_from_env()`:

```python theme={null}
from qoder_agent_sdk import QoderAgentOptions, access_token_from_env, query

options = QoderAgentOptions(auth=access_token_from_env())

async for message in query(prompt="Hello", options=options):
    print(message)
```

The SDK reads this environment variable before starting qodercli and writes the parsed access token into a one-time auth payload. You typically don't need to pass the PAT via the `env` option; if `options.env` is explicitly provided, the SDK reads the same-named variable from it first.

> **Security Note**: Do not hard-code PATs in your code repository. Inject them via environment variables or a secrets management service.

<div id="choosing-between-query-and-qodersdkclient" />

<div id="choosingbetweenqueryandqodersdkclient" />

## Choosing Between `query()` and `QoderSDKClient`

| Scenario                                                        | Use              | Why                                                           |
| --------------------------------------------------------------- | ---------------- | ------------------------------------------------------------- |
| One-shot, stateless task (single prompt → get result)           | `query()`        | Async generator, ready to use, finishes when the process ends |
| Multi-turn conversation, deciding the next step from each reply | `QoderSDKClient` | Long-lived connection, stateful                               |

<div id="minimal-example-query" />

<div id="minimalexamplequery" />

### Minimal example: `query()`

```python theme={null}
import anyio

from qoder_agent_sdk import (
    AssistantMessage,
    QoderAgentOptions,
    TextBlock,
    access_token_from_env,
    query,
)


async def main():
    options = QoderAgentOptions(auth=access_token_from_env())

    async for msg in query(prompt="What is 2 + 2?", options=options):
        if isinstance(msg, AssistantMessage):
            for block in msg.content:
                if isinstance(block, TextBlock):
                    print(block.text)


anyio.run(main)
```

<div id="minimal-example-qodersdkclient" />

<div id="minimalexampleqodersdkclient" />

### Minimal example: `QoderSDKClient`

```python theme={null}
import anyio

from qoder_agent_sdk import (
    AssistantMessage,
    QoderAgentOptions,
    QoderSDKClient,
    TextBlock,
    access_token_from_env,
)


async def main():
    options = QoderAgentOptions(auth=access_token_from_env())

    async with QoderSDKClient(options=options) as client:
        await client.query("What's the capital of France?")
        async for msg in client.receive_response():
            if isinstance(msg, AssistantMessage):
                for block in msg.content:
                    if isinstance(block, TextBlock):
                        print(block.text)

        # Decide the next turn from what we just heard
        await client.query("What's the population of that city?")
        async for msg in client.receive_response():
            if isinstance(msg, AssistantMessage):
                for block in msg.content:
                    if isinstance(block, TextBlock):
                        print(block.text)


anyio.run(main)
```

<div id="full-example" />

<div id="fullexample" />

## Full example

Create `agent.py`:

```python theme={null}
import anyio

from qoder_agent_sdk import (
    AssistantMessage,
    QoderAgentOptions,
    ResultMessage,
    TextBlock,
    ToolUseBlock,
    access_token_from_env,
    query,
)


async def main():
    options = QoderAgentOptions(
        auth=access_token_from_env(),
        allowed_tools=["Read", "Write", "Edit", "Glob", "Grep", "Bash"],
        permission_mode="acceptEdits",  # Auto-approve file edits
    )

    async for message in query(
        prompt=(
            "Analyze the codebase, find functions without test coverage, "
            "and write unit tests for them."
        ),
        options=options,
    ):
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    print(block.text)              # AI text response
                elif isinstance(block, ToolUseBlock):
                    print(f"Tool: {block.name}")   # Tool being called
        elif isinstance(message, ResultMessage):
            print(f"Done: {message.subtype}")      # Final result


anyio.run(main)
```

```bash theme={null}
python agent.py
```

The Agent will autonomously browse the project, find functions lacking test coverage, generate test files, and run them for verification.

<div id="next-steps" />

<div id="nextsteps" />

## Next Steps

* [SDK Authentication](/en/cli/sdk/python/authentication) — PAT, environment variables, and auth error handling
* [Multi-turn Conversation](/en/cli/sdk/python/multi-turn-conversation) — Multi-message session, managing the session lifecycle
* [Streaming Output](/en/cli/sdk/python/streaming-output) — Receive incremental content in real time, typewriter effect
* [Hooks](/en/cli/sdk/python/hooks) and [Permissions](/en/cli/sdk/python/permissions) — Intercept and approve tool calls in the agent loop
