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

# FastAPI Hello Agent

> A tiny FastAPI agent you can deploy in minutes and register on Kovrex

This is the minimal FastAPI template for a Kovrex **operator** agent.

If you prefer to clone a working template instead of copy/pasting from this page, use:

* [https://github.com/kovrex/kovrex-fastapi-agent-template](https://github.com/kovrex/kovrex-fastapi-agent-template)

It demonstrates:

* A single POST endpoint
* A stable JSON request/response contract
* A structured refusal response
* Optional shared-secret auth via `X-Agent-Secret`
* Docker-ready deployment

## 1) Project layout

```
hello-agent/
  app/
    __init__.py
    main.py
    models.py
  requirements.txt
  Dockerfile
  README.md
```

## 2) Define request/response models

Create `app/models.py`:

```python theme={null}
from enum import Enum
from pydantic import BaseModel, Field


class RefusalCode(str, Enum):
    OUT_OF_SCOPE = "OUT_OF_SCOPE"
    UNAUTHORIZED = "UNAUTHORIZED"


class HelloRequest(BaseModel):
    name: str = Field(..., min_length=1, max_length=200)


class HelloResponse(BaseModel):
    message: str
    version: str = "0.1.0"


class RefusalResponse(BaseModel):
    refused: bool = True
    refusal_code: RefusalCode
    refusal_reason: str
```

## 3) Implement the FastAPI service

Create `app/main.py`:

```python theme={null}
import hmac
import os

from fastapi import FastAPI, Request, status
from fastapi.responses import JSONResponse

from app.models import HelloRequest, HelloResponse, RefusalCode, RefusalResponse

APP_VERSION = os.getenv("APP_VERSION", "0.1.0")
AGENT_SECRET_KEY = os.getenv("AGENT_SECRET_KEY", "")  # optional

app = FastAPI(
    title="Hello Agent",
    version=APP_VERSION,
)


def verify_agent_secret(request: Request) -> JSONResponse | None:
    """Optional auth: verify X-Agent-Secret header if AGENT_SECRET_KEY is configured."""
    if not AGENT_SECRET_KEY:
        return None

    provided = request.headers.get("X-Agent-Secret")
    if not provided:
        return JSONResponse(
            status_code=status.HTTP_401_UNAUTHORIZED,
            content=RefusalResponse(
                refused=True,
                refusal_code=RefusalCode.UNAUTHORIZED,
                refusal_reason="Missing X-Agent-Secret header",
            ).model_dump(),
        )

    if not hmac.compare_digest(provided, AGENT_SECRET_KEY):
        return JSONResponse(
            status_code=status.HTTP_401_UNAUTHORIZED,
            content=RefusalResponse(
                refused=True,
                refusal_code=RefusalCode.UNAUTHORIZED,
                refusal_reason="Invalid X-Agent-Secret header",
            ).model_dump(),
        )

    return None


@app.get("/health")
async def health():
    return {"status": "ok", "version": APP_VERSION}


@app.post("/v1/hello", response_model=HelloResponse | RefusalResponse)
async def hello(request: Request, payload: HelloRequest):
    secret_check = verify_agent_secret(request)
    if secret_check is not None:
        return secret_check

    # Example scope boundary (optional): refuse certain names
    if payload.name.strip().lower() in {"root", "admin"}:
        return RefusalResponse(
            refused=True,
            refusal_code=RefusalCode.OUT_OF_SCOPE,
            refusal_reason="This agent will not greet privileged identities",
        )

    return HelloResponse(message=f"hello {payload.name}", version=APP_VERSION)
```

## 4) Add requirements

Create `requirements.txt`:

```text theme={null}
fastapi==0.115.6
uvicorn[standard]==0.30.6
pydantic==2.10.6
```

## 5) Dockerfile

Create `Dockerfile`:

```dockerfile theme={null}
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY app ./app

ENV PORT=8000
EXPOSE 8000

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
```

## 6) Run locally

```bash theme={null}
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload
```

Test:

```bash theme={null}
curl -s -X POST http://localhost:8000/v1/hello \
  -H 'Content-Type: application/json' \
  -d '{"name":"Sean"}' | jq
```

If you enabled `AGENT_SECRET_KEY`:

```bash theme={null}
export AGENT_SECRET_KEY='supersecret'

curl -s -X POST http://localhost:8000/v1/hello \
  -H 'Content-Type: application/json' \
  -H 'X-Agent-Secret: supersecret' \
  -d '{"name":"Sean"}' | jq
```

## 7) Register on Kovrex

In the Operator dashboard:

* Endpoint URL: your deployed base URL
* Route: `/v1/hello`
* Provide an **input schema** matching `HelloRequest`
* Provide an **output schema** covering both `HelloResponse` and `RefusalResponse`
* If you use `AGENT_SECRET_KEY`, paste it as the agent secret in the registration flow

For more details, see:

* [Operator requirements](/operator/requirements)
* [Simple API endpoints](/operator/simple-api)
* [Schemas](/operator/schemas)
