Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
**/venv
**/node_modules
**/__pycache__
*.env.local
**/.env
**/.env.local
*.env.local
**/tests
docs/
.github/
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ The sections below (Start Here, Patterns, Anti-Patterns, etc.) remain the canoni
- Prefer the smallest change that keeps local mode and deployed mode aligned.
- Keep Python-specific agent lifecycle changes in `server`.
- Keep browser state and RTC/RTM lifecycle changes in `web`.
- Treat `server/.env.local` as CLI-managed by default.
- Treat `server/.env` as CLI-managed by default.
- If you change request or response contracts, update the web client, backend, contract checks, and README together.

## Commands
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ cd agent-quickstart-python
agora login
agora project use <your-project>
bun run setup
agora project env write server/.env.local
agora quickstart env write .
bun run doctor:local
bun run dev
```

`bun run setup` preserves a configured `server/.env`, copies a legacy `server/.env.local` when needed, and prints the credential-writing step when the resulting file lacks real Agora values. Setup and `doctor:local` replace an untouched example file with configured legacy credentials. This supports CLI versions that wrote `.env.local`.

Services:

- Frontend: `http://localhost:3000`
Expand All @@ -72,15 +74,14 @@ Set backend env values:
```bash
AGORA_APP_ID=your_agora_app_id
AGORA_APP_CERTIFICATE=your_agora_app_certificate
AGENT_GREETING=optional_custom_greeting
```

To export local env values from the Agora CLI-bound project:

```bash
agora project use <your-project>
agora project env write server/.env.local
rg "^(AGORA_APP_ID|AGORA_APP_CERTIFICATE)=" server/.env.local
agora quickstart env write .
rg "^(AGORA_APP_ID|AGORA_APP_CERTIFICATE)=" server/.env
```

## Environment variables
Expand All @@ -91,7 +92,6 @@ Primary backend env file: [`server/.env.example`](server/.env.example).
| --- | :---: | :---: | --- |
| `AGORA_APP_ID` | ✅ | — | Agora Console -> Project -> App ID |
| `AGORA_APP_CERTIFICATE` | ✅ | — | Agora Console -> Project -> App Certificate (server only) |
| `AGENT_GREETING` | | built-in greeting | Optional opening line override |
| `PORT` | | `8000` | FastAPI server port |
| `AGENT_BACKEND_URL` (web deploy) | ✅ | — | Required in deployed `web` app when proxying to external FastAPI |

Expand Down Expand Up @@ -153,8 +153,8 @@ The browser talks to Next.js `/api/*` routes. In local mode, Next rewrites those
## Troubleshooting

- **Agent does not join or transcripts are missing:** run `agora project doctor --deep`.
- **Missing credentials:** run `agora project env write server/.env.local`.
- **Auth errors from backend:** confirm `AGORA_APP_ID` and `AGORA_APP_CERTIFICATE` are set in `server/.env.local`.
- **Missing credentials:** run `agora quickstart env write .`.
- **Auth errors from backend:** confirm `AGORA_APP_ID` and `AGORA_APP_CERTIFICATE` are set in `server/.env`.
- **Frontend cannot reach backend:** confirm `AGENT_BACKEND_URL=http://localhost:8000` in local frontend scripts.
- **Unsure who owns `/api/*`:** Next owns browser-facing `/api/*`; FastAPI owns `/get_config`, `/startAgent`, `/stopAgent`.

Expand Down
2 changes: 1 addition & 1 deletion docs/ai/L0_repo_card.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
| Language | Python 3.10+ (FastAPI + uvicorn) backend + Next.js 16 / React 19 web |
| Deploy Target | `web/` as Next.js app, `server/` as a reachable FastAPI service |
| Owner | Agora Conversational AI DevEx |
| Last Reviewed | 2026-06-11 |
| Last Reviewed | 2026-08-21 |
| Recipe Role | `base` |
| Recipe Version | `1.0.0` |
| Recipe Status | `experimental` |
Expand Down
15 changes: 3 additions & 12 deletions docs/ai/L1/01_setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ bun run setup
# runs: setup:env → setup:backend → setup:frontend → setup:done
```

`setup:env` copies `server/.env.example` → `server/.env.local` if missing. `setup:backend` recreates `server/venv`, upgrades pip, and installs `requirements.txt`. `setup:frontend` runs `bun install`. `setup:deps` exists for `bun run dev:check`, not for `bun run setup`.
`setup:env` preserves a configured `server/.env`, copies a legacy `server/.env.local` to `server/.env` when needed, or seeds `server/.env` from `server/.env.example`. If the seeded file has both example values and a CLI version writes valid credentials to the legacy path, `setup:env` and `doctor:local` copy those credentials into `server/.env`. The completion message omits the credential-writing command when the resulting file has non-placeholder Agora credentials. `setup:backend` recreates `server/venv`, upgrades pip, and installs `requirements.txt`. `setup:frontend` runs `bun install`. `setup:deps` exists for `bun run dev:check`, not for `bun run setup`.

> The package.json scripts use `server/venv/` (no leading dot). `bun run dev:backend` activates `server/venv` and runs `python src/server.py` from inside `server/`. If you create the venv under a different name you'll need to adjust the scripts or symlink.

Expand All @@ -37,22 +37,13 @@ bun run setup
```
AGORA_APP_ID=your_agora_app_id
AGORA_APP_CERTIFICATE=your_agora_app_certificate
AGENT_GREETING=Hi there! I'm Ada, your virtual assistant from Agora. How can I help?
PORT=8000
```

`web/.env.local.example`:

```
# Required: Next rewrites /api/* requests to the Python backend.
AGENT_BACKEND_URL=http://localhost:8000
```

| Variable | Process | Required | Notes |
| ------------------------ | -------------------- | -------- | --------------------------------------------------------------------- |
| `AGORA_APP_ID` | Python (server) | Yes | Loaded by `Agent.__init__` via `os.environ`. |
| `AGORA_APP_CERTIFICATE` | Python (server) | Yes | Server-only. |
| `AGENT_GREETING` | Python (server) | No | Optional first utterance. |
| `PORT` | Python (server) | No | Default `8000` (`server.py`). |
| `AGENT_BACKEND_URL` | Next build (web) | Yes for rewrites | Empty/missing → no `/api/*` rewrites registered. Required by `web/scripts/doctor.ts`. |
| `NEXT_PUBLIC_AGENT_UID` | Browser (web) | No | Optional UID override read in `ConversationComponent.tsx`. |
Expand All @@ -78,7 +69,7 @@ bun run dev # setup:env → setup:deps → concurrently {back
bun run dev:backend # python3 server/src/server.py
bun run dev:frontend # cd web && AGENT_BACKEND_URL=http://localhost:8000 bun run dev
bun run doctor # bun + node_modules sanity
bun run doctor:local # adds python3 + .env.local + AGORA_* presence
bun run doctor:local # adds python3 + server/.env + AGORA_* presence
bun run build # bun --filter web build
bun run verify # doctor + verify:web:api + verify:web:build
bun run verify:local # doctor:local + verify:backend + verify:local:fastapi + verify:web:proxy + verify:web:build
Expand Down Expand Up @@ -107,7 +98,7 @@ bun run clean # remove backend venv, node_modules, .next, web/d
## Common Setup Failures

- `bun run doctor:local` fails on **"python3 not found"** → install Python ≥ 3.10.
- Doctor fails on missing `server/.env.local` → run `bun run setup:env` or copy from `server/.env.example`.
- Doctor fails on missing or placeholder credentials in `server/.env` → run `agora quickstart env write .`.
- `cd web && bun run doctor` rejects empty/invalid `AGENT_BACKEND_URL` → ensure the URL is `http://` or `https://`.
- `verify:web:api` fails on a new route → extend `web/scripts/verify-api-contracts.ts` to cover it.

Expand Down
2 changes: 1 addition & 1 deletion docs/ai/L1/02_architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ If `AGENT_BACKEND_URL` is unset/empty, **no rewrites register** — the client c

- `FastAPI(title="...", version="2.0.0")`.
- `CORSMiddleware` with `allow_origins=["*"]`, `allow_credentials=True`.
- Reads `server/.env.local` then `server/.env` via `python-dotenv` at startup, resolved relative to `server/src/server.py`.
- Reads `server/.env` via `python-dotenv` at startup, resolved relative to `server/src/server.py`.
- Constructs a single `Agent` instance at import time (`agent = Agent()`).
- Routes registered on an `APIRouter`: `GET /get_config`, `POST /startAgent`, `POST /stopAgent`.
- All responses use the envelope `{ "code": 0, "msg": "success", "data": ... }`.
Expand Down
4 changes: 2 additions & 2 deletions docs/ai/L1/05_workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
Edit `server/src/agent.py`:

- **Prompt:** modify the `ADA_PROMPT` constant.
- **Greeting:** set `AGENT_GREETING` in `server/.env.local`, or change the default in the constructor.
- **Greeting:** change `DEFAULT_GREETING` in `server/src/agent.py`.
- **VAD:** edit `turn_detection` dict (start/end mode, speech threshold, silence/interrupt durations).
- **LLM:** change the `OpenAI(...)` constructor (model, history, BYOK key, base URL).
- **STT:** change the `DeepgramSTT(...)` constructor.
Expand All @@ -33,7 +33,7 @@ After editing, run `bun run verify:backend && bun run verify:web:api`.
## Deploy the Web and Backend Separately

- **Web (Next.js):** build via `cd web && bun run build`. Configure `AGENT_BACKEND_URL` on the deploy target to the public URL of your FastAPI service. Serve with `bun run start` or any Node hosting platform.
- **Backend (FastAPI):** install deps from `server/requirements.txt`, set `AGORA_APP_ID`, `AGORA_APP_CERTIFICATE`, optional `AGENT_GREETING`/`PORT`, and run `python3 server/src/server.py` or `uvicorn server.src.server:app --host 0.0.0.0 --port $PORT`.
- **Backend (FastAPI):** install deps from `server/requirements.txt`, set `AGORA_APP_ID`, `AGORA_APP_CERTIFICATE`, and optionally `PORT`, then run `python3 server/src/server.py` or `uvicorn server.src.server:app --host 0.0.0.0 --port $PORT`.
- The two deploys never share env vars. The browser only ever needs `/api/*` to resolve via the rewrite layer.

## Verify Locally
Expand Down
2 changes: 1 addition & 1 deletion docs/ai/L1/06_interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ CORS middleware: `allow_origins=["*"]`, `allow_credentials=True`.
| Scope | Variable |
| ---------------------- | ----------------------------------------- |
| Python server (required) | `AGORA_APP_ID`, `AGORA_APP_CERTIFICATE` |
| Python server (optional) | `AGENT_GREETING`, `PORT` |
| Python server (optional) | `PORT` |
| Next build | `AGENT_BACKEND_URL` |
| Browser | `NEXT_PUBLIC_AGENT_UID` (optional) |

Expand Down
2 changes: 1 addition & 1 deletion docs/ai/L1/07_gotchas.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ The quickstart deliberately uses `generate_convo_ai_token` for both RTC and RTM

## Env Loading Is File-Relative

`server.py` derives the `server/` directory from `__file__` and loads `server/.env.local` then `server/.env`. Running from the repo root still finds those files; missing `AGORA_APP_ID` or `AGORA_APP_CERTIFICATE` leaves `agent = None` and routes return `500`.
`server.py` derives the `server/` directory from `__file__` and loads `server/.env`. Running from the repo root still finds that file; missing `AGORA_APP_ID` or `AGORA_APP_CERTIFICATE` leaves `agent = None` and routes return `500`.

## `server/scripts/run_fake_server.py` Is for Tests Only

Expand Down
6 changes: 3 additions & 3 deletions docs/ai/L1/08_security.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
| -------------- | ---------------------------------------------------------------------- |
| Browser | `NEXT_PUBLIC_AGENT_UID` (optional) |
| Next build/run | `AGENT_BACKEND_URL` |
| FastAPI | `AGORA_APP_ID`, `AGORA_APP_CERTIFICATE`, `AGENT_GREETING`, `PORT` |
| FastAPI | `AGORA_APP_ID`, `AGORA_APP_CERTIFICATE`, `PORT` |

Mark `AGORA_APP_CERTIFICATE` as a sensitive secret in whichever host runs the Python service. The certificate value never appears in `web/`.

Expand Down Expand Up @@ -62,9 +62,9 @@ If you need real auth, add a FastAPI dependency that validates a header on each

## Secret Handling Rules

- `server/.env.local` is the developer's secret store; do not commit it.
- `server/.env` is the developer's secret store; do not commit it.
- `server/.env.example` documents shape only — never put real values there.
- `load_dotenv` reads `server/.env.local` then `server/.env` using a path derived from `server/src/server.py`; missing credentials fail startup initialization and leave routes returning `500`.
- `load_dotenv` reads `server/.env` using a path derived from `server/src/server.py`; missing credentials fail startup initialization and leave routes returning `500`.
- Do not log full env. `logger.error("failed: %s", err)` is fine; `logger.error(os.environ)` is not.

## CSP / Security Headers
Expand Down
6 changes: 3 additions & 3 deletions docs/ai/L1/L2/from_scratch_bootstrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Why: provider schemas, SDK builder fields, token behavior, and RTM event details

| Need | Read First | Deep Detail | Source Reference |
| --- | --- | --- | --- |
| Project setup, commands, env vars | [../01_setup.md](../01_setup.md) | none | `package.json`, `server/.env.example`, `web/.env.local.example` |
| Project setup, commands, env vars | [../01_setup.md](../01_setup.md) | none | `package.json`, `server/.env.example` |
| End-to-end architecture and data flow | [../02_architecture.md](../02_architecture.md) | [session_lifecycle.md](session_lifecycle.md) | `web/src/components/LandingPage.tsx`, `web/src/components/ConversationComponent.tsx`, `server/src/server.py` |
| File/module responsibilities | [../03_code_map.md](../03_code_map.md) | none | `web/`, `server/`, `web/scripts/` |
| API payloads and response shapes | [../06_interfaces.md](../06_interfaces.md) | [verification_scripts.md](verification_scripts.md) | `server/src/server.py`, `web/src/services/api.ts`, `web/next.config.ts` |
Expand All @@ -27,9 +27,9 @@ Implement these pieces in order:

1. Create a bun workspace with `web` as a workspace member and root scripts that orchestrate backend, frontend, setup, doctor, verify, and clean tasks.
2. Create `server/` with FastAPI, uvicorn, python-dotenv, and `agora-agents>=2.0.0` in `server/requirements.txt`.
3. Add `server/.env.example` with `AGORA_APP_ID`, `AGORA_APP_CERTIFICATE`, optional `AGENT_GREETING`, and optional `PORT`.
3. Add `server/.env.example` with `AGORA_APP_ID`, `AGORA_APP_CERTIFICATE`, and optional `PORT`.
4. Implement `server/src/agent.py` with an `Agent` class that reads env once, constructs `AsyncAgora`, builds `AgoraAgent` with managed `DeepgramSTT`, `OpenAI`, `MiniMaxTTS`, starts async sessions, stores sessions by `agent_id`, and stops by active session or `client.stop_agent`.
5. Implement `server/src/server.py` with `GET /get_config`, `POST /startAgent`, and `POST /stopAgent`; load env file-relative from `server/.env.local` then `server/.env`.
5. Implement `server/src/server.py` with `GET /get_config`, `POST /startAgent`, and `POST /stopAgent`; load `server/.env` relative to the source file.
6. In `GET /get_config`, replace missing, zero, or negative UIDs with a generated non-zero UID, generate a one-hour RTC+RTM token with `generate_convo_ai_token`, and return `{ app_id, token, uid, channel_name, agent_uid }`.
7. Create a Next.js App Router web app under `web/` with React, TypeScript, Tailwind, `agora-rtc-react`, `agora-rtm`, `agora-agent-client-toolkit`, and `agora-agent-uikit`.
8. Implement `web/next.config.ts` rewrites for `/api/get_config`, `/api/startAgent`, and `/api/stopAgent` to `${AGENT_BACKEND_URL}/...`; return no rewrites when the env var is missing.
Expand Down
2 changes: 1 addition & 1 deletion docs/ai/L1/L2/managed_agent_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Edit the `ADA_PROMPT` string constant at the top of `agent.py`. Keep it concise

### Change the greeting

Set `AGENT_GREETING` in `server/.env.local`, or change the inline fallback string in `Agent.__init__`.
Change `DEFAULT_GREETING` in `server/src/agent.py`.

### Change VAD

Expand Down
4 changes: 2 additions & 2 deletions docs/ai/RECIPE.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Do not recreate Agora ConvoAI integration from memory. Provider schemas, SDK bui
| ID | Surface | How to extend | Required follow-up |
| -- | ------- | ------------- | ------------------ |
| `api.routes` | `server/src/server.py`, `web/next.config.ts`, `web/src/services/api.ts` | Add FastAPI route, add rewrite, add browser fetch helper. | Extend `web/scripts/verify-api-contracts.ts`; add smoke coverage if the route belongs in local verification. |
| `agent.managed-config` | `server/src/agent.py` | Change `ADA_PROMPT`, `AGENT_GREETING`, `turn_detection`, `OpenAI`, `DeepgramSTT`, `MiniMaxTTS`, `parameters`, or session options. | Run backend compile and local FastAPI smoke checks; document new env vars in `server/.env.example`. |
| `agent.managed-config` | `server/src/agent.py` | Change `ADA_PROMPT`, `DEFAULT_GREETING`, `turn_detection`, `OpenAI`, `DeepgramSTT`, `MiniMaxTTS`, `parameters`, or session options. | Run backend compile and local FastAPI smoke checks; document new env vars in `server/.env.example`. |
| `web.conversation-ui` | `web/src/components/*`, `web/src/lib/conversation.ts` | Customize pre-call, transcript, metrics, connection status, microphone, or visualizer UI. | Preserve RTC/RTM lifecycle ownership and transcript UID normalization. |
| `verification.contracts` | `web/scripts/*.ts`, root `package.json` | Add contract checks for new browser/backend boundaries. | Keep checks runnable without live Agora credentials where possible. |

Expand All @@ -76,7 +76,7 @@ Do not recreate Agora ConvoAI integration from memory. Provider schemas, SDK bui
| Contract | Stable shape |
| -------- | ------------ |
| Required backend env | `AGORA_APP_ID`, `AGORA_APP_CERTIFICATE` |
| Optional backend env | `AGENT_GREETING`, `PORT` |
| Optional backend env | `PORT` |
| Required web deploy env | `AGENT_BACKEND_URL` |
| Optional browser env | `NEXT_PUBLIC_AGENT_UID` |
| `GET /api/get_config` | Query `channel?`, `uid?`; returns `data.app_id`, `data.token`, `data.uid`, `data.channel_name`, `data.agent_uid`. |
Expand Down
Loading
Loading