# Dynamic Instructions

> Update the agent's system prompt mid-session.

Use template variables and a live update endpoint to change the agent's instructions without restarting.

- Author: Agora
- Updated: 2026-06-12
- Difficulty: Beginner
- Categories: voice-ai
- Platforms: Python, TypeScript
- Use cases: Conversation Design, Voice AI
- Capabilities: Conversational AI, Voice Agent, Prompt Management
- [Recipe page](https://recipes.agora.io/recipes/dynamic-instructions)
- [Implementation repository](https://github.com/AgoraIO-Conversational-AI/recipe-agent-instructions)
- [Source recipe](https://github.com/AgoraIO-Conversational-AI/recipe-agent-instructions/blob/main/README.md)
- [Raw source Markdown](https://raw.githubusercontent.com/AgoraIO-Conversational-AI/recipe-agent-instructions/main/README.md)
- [All recipes](https://recipes.agora.io/llms.txt)

## Use with Agora CLI

agora init my-dynamic-instructions --recipe dynamic-instructions

## Implementation guide

# Agora Conversational AI — Instructions Recipe (Python)

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
[![Python](https://img.shields.io/badge/python-%3E%3D3.10-blue)](https://www.python.org/)
[![Bun](https://img.shields.io/badge/bun-latest-black)](https://bun.sh/)

The **instructions** recipe in the Agora Conversational AI recipes family. It
demonstrates how to configure the agent through system-prompt features, context
injection, and live runtime updates — all using Agora's **managed OpenAI vendor**.

This recipe is **zero-key**: it uses Agora's **managed OpenAI vendor** (keyless,
just like Deepgram STT and MiniMax TTS). `OPENAI_API_KEY` is **optional** — set
it only if your Agora account requires a bring-your-own key. There is no separate
LLM service to run or expose.

## Prerequisites

- [Python 3.10+](https://www.python.org/)
- [Bun](https://bun.sh/)
- Agora App ID + App Certificate (the [Agora CLI](https://github.com/AgoraIO/cli) makes this easy)

The same commands work on macOS, Linux, and Windows. On macOS/Linux, setup uses
`python3`; on Windows, it uses the Python launcher (`py`) or `python`. WSL and
virtualenv activation are not required.

## Run It

```bash
# 1. Install dependencies
bun run setup

# 2. Add Agora credentials (CLI), or edit server/.env.local by hand
agora login
agora project use <your-project>
agora project env write server/.env.local

# 3. Start the agent backend and web frontend
bun run dev
```

Open [http://localhost:3000](http://localhost:3000) → **Start Conversation** → speak.

### Working from a clone

If you cloned this repo (rather than scaffolding via the Agora CLI), the steps
above are complete as written: `bun run setup` creates the Python venv and installs
web dependencies, then `bun run dev` brings up both services. You still need Agora
credentials in `server/.env.local` before a conversation can connect.

Services:

- Frontend — http://localhost:3000
- Backend — http://localhost:8000
- Mock LLM — n/a (Agora-managed)
- API docs — http://localhost:8000/docs

## Deploy

Deploy `web` (Next.js) and `server` (a reachable FastAPI backend). Set
`AGENT_BACKEND_URL` in the web deployment so the Next rewrites reach the backend.

A backend-only Docker image is published to
`ghcr.io/AgoraIO-Conversational-AI/recipe-agent-instructions` on `v*` tags. It
runs the agent backend on **:8000 only** (no separate LLM port — OpenAI is
Agora-managed).

## Environment variables

Backend env file: [`server/.env.example`](https://github.com/AgoraIO-Conversational-AI/recipe-agent-instructions/blob/main/server/.env.example).

| Variable | Required | Default | Notes |
| --- | :---: | :---: | --- |
| `AGORA_APP_ID` | ✅ | — | Agora Console → Project → App ID |
| `AGORA_APP_CERTIFICATE` | ✅ | — | Agora Console → Project → App Certificate |
| `OPENAI_API_KEY` | | — | Optional — Agora manages the OpenAI key by default; set only for bring-your-own key |
| `OPENAI_MODEL` | | `gpt-4o-mini` | OpenAI model name |
| `REPLY_STYLE` | | `normal` | `normal` or `short` (short → terse + low max_tokens) |
| `ASSISTANT_NAME` | | `Ada` | Injected as `{{assistant_name}}` in the system prompt |
| `AGENT_EXIT_MESSAGE` | | `Thanks for chatting — goodbye!` | Closing instruction appended to the system prompt |
| `AGENT_GREETING` | | built-in | Optional opening line override |
| `AGENT_BACKEND_URL` (web deploy) | ✅ | — | Required when deploying `web` separately |

## Commands

```bash
bun run setup            # install web deps + create server/ venv
bun run dev              # backend (:8000) + web (:3000)

bun run doctor           # prerequisite check (no creds needed)
bun run doctor:local     # + .env.local + credentials check

bun run verify           # web-only gate (no Agora creds needed)
bun run verify:local     # full local gate: backend compile + web build
bun run clean            # remove venvs and build artifacts
```

Tests run standalone (no Agora cloud needed): `pytest` in `server/`, plus
`bun run verify` in `web/`. CI runs them on Linux/macOS/Windows × Python 3.10 & 3.13.

## Architecture

```
Browser (localhost:3000)
  │  fetch /api/*
  ▼
Next.js  ──rewrite──▶  Agent backend  (server/, localhost:8000)
                          │  starts agent session (managed OpenAI vendor)
                          ▼
                       Agora ConvoAI Cloud
                          │  Deepgram STT (managed)
                          │  OpenAI LLM (Agora-managed, keyless)
                          │  MiniMax TTS (managed)
                          ▼
                       RTM transcript / metrics → web UI
```

The browser only ever calls Next `/api/*`, which rewrites to the agent backend.
The agent backend owns Agora tokens and agent lifecycle. LLM calls go through
Agora's managed OpenAI integration — no separate endpoint to expose. See
[ARCHITECTURE.md](https://github.com/AgoraIO-Conversational-AI/recipe-agent-instructions/blob/main/ARCHITECTURE.md).

## What You Get

- A **Next.js** web client (:3000) that drives the RTC/RTM lifecycle and only
  ever calls `/api/*`.
- A **FastAPI** agent backend (:8000) that owns Agora token generation and the
  agent session lifecycle.
- The `/api/get_config` · `/api/startAgent` · `/api/stopAgent` contract between
  the web client and the backend (Next rewrites, no Route Handlers).
- **Agora-managed keyless OpenAI** — the same zero-key model used for Deepgram STT
  and MiniMax TTS. Agora provisions OpenAI access on your behalf; `OPENAI_API_KEY`
  is optional (set it only if your Agora account requires a bring-your-own key).
- **`template_variables`** — inject `{{assistant_name}}` and `{{today}}` into the
  system prompt at agent-start time.
- **`REPLY_STYLE`** — set to `short` for terse one-sentence answers (low
  `max_tokens`) or `normal` (default) for fuller responses.
- **`POST /updateInstructions`** — swap the running agent's system prompt at any
  time via Agora's update API without restarting the session.
- **`AGENT_EXIT_MESSAGE`** — append a closing instruction so the agent delivers a
  consistent goodbye line when the user ends the conversation.

## How It Works

1. The browser calls `/api/get_config`, which Next rewrites to the backend; the
   backend mints an Agora token from `AGORA_APP_ID` + `AGORA_APP_CERTIFICATE`.
2. The browser joins the RTC channel, then calls `/api/startAgent`; the backend
   starts an agent session using the managed `OpenAI` vendor with the configured
   system prompt (including `template_variables` and `REPLY_STYLE` settings).
3. The user speaks. Agora runs STT (Deepgram nova-3), then sends the transcript
   to the Agora-managed OpenAI endpoint.
4. OpenAI processes the request using the configured `OPENAI_MODEL` and returns a
   response. The `REPLY_STYLE` setting controls verbosity (`short` caps
   `max_tokens`; `normal` allows fuller replies).
5. Agora runs TTS (MiniMax) on the reply and plays it back in the channel.
6. While a session is running, you can swap the agent's system prompt without
   restarting — call `POST /updateInstructions` with the agent ID and new
   instructions:

   ```bash
   curl -X POST http://localhost:8000/updateInstructions \
     -H "Content-Type: application/json" \
     -d '{"agentId": "<agent_id_from_startAgent>", "instructions": "You are a pirate. Arr!"}'
   ```

   The next agent turn will use the new prompt. This is the key capability this
   recipe demonstrates: a live configurable agent personality driven entirely by
   system-prompt features, with no separate LLM service to maintain.
7. `AGENT_EXIT_MESSAGE` appends a closing instruction to the system prompt so the
   agent delivers a consistent goodbye line when the conversation ends.
8. `/api/stopAgent` ends the session.

## Repo Map

- `web/` — Next.js frontend (:3000); RTC/RTM lifecycle and UI.
- `server/` — FastAPI agent backend (:8000); Agora tokens + agent lifecycle, managed OpenAI vendor.
- `ARCHITECTURE.md` — system shape and component boundaries.
- `AGENTS.md` — guide for coding agents working in this repo.

## Troubleshooting

| Problem | Fix |
| --- | --- |
| Agent starts but never responds | Check `OPENAI_MODEL` is a valid model name. If your Agora account requires a key, ensure `OPENAI_API_KEY` is set in `server/.env.local`. |
| Local calls fail / hang under a proxy | Configure your proxy to route `127.0.0.1` and `localhost` DIRECT. |

## More Docs

- [ARCHITECTURE.md](https://github.com/AgoraIO-Conversational-AI/recipe-agent-instructions/blob/main/ARCHITECTURE.md)
- [AGENTS.md](https://github.com/AgoraIO-Conversational-AI/recipe-agent-instructions/blob/main/AGENTS.md)

## License

Released under the [MIT License](https://github.com/AgoraIO-Conversational-AI/recipe-agent-instructions/blob/main/LICENSE).


## Recipe prompt

You are implementing the "Dynamic Instructions" recipe in this project.

Read the recipe markdown first:
https://raw.githubusercontent.com/AgoraIO-Conversational-AI/recipe-agent-instructions/main/README.md

Use the source repository for cross-reference:
https://github.com/AgoraIO-Conversational-AI/recipe-agent-instructions

Build this recipe into the user's app using the markdown as the implementation guide. Inspect related source files through the repository links when the recipe points to them. Ask before installing new dependencies.
