Build Your First Voice Agent in Go with the Agora Agents SDK
Create a voice interview partner, then explore how a Go backend starts and stops the conversation.
In this tutorial, you’ll run a Go voice agent that helps you practice talking about a project. Open the app in your browser, describe something you built, and hear the agent ask a follow-up based on your answer. Your project can use any programming language.
You’ll use the existing Agora Go Quickstart Recipe, which provides a Gin backend and a Next.js client. The browser handles microphone input and playback; the Go service configures the cloud agent and starts and stops its sessions.
Before you start
- Go 1.23 or later and basic familiarity with Go functions and structs.
- Node.js 20.9 or later and pnpm. The starter pins pnpm 10.23.0.
- The Agora CLI, installed and available as
agora. - An Agora project with an App ID and App Certificate, and RTC, RTM, and Conversational AI managed-provider support enabled. You can manage your project in the Agora Console.
- A browser with microphone access. Headphones help keep the agent’s voice out of your microphone.
The project uses Make and Bash. Follow along on macOS, Linux, or Windows through WSL with those tools available.
1. Get start
Sign in and create a project from the recipe:
agora login
agora init my-go-agent --recipe golang-quickstart
cd my-go-agent
make setupmake setup downloads the Go modules, installs the frontend workspace dependencies, and prepares server/.env. The main files you'll use are:
server/
main.go HTTP routes and environment loading
agent.go Agent instructions, providers, and sessions
client/
next.config.ts Browser API rewrites to the Go backend
Makefile Setup, development, and verification commandsOpen server/.env and replace the two example credential values with those from your Agora project. Keep the other entries supplied by setup:
AGORA_APP_ID=your_agora_app_id
AGORA_APP_CERTIFICATE=your_agora_app_certificateAlternatively, populate the environment file through the CLI from the project root, replacing <your-project> with your project's name or ID:
agora project use <your-project>
agora quickstart env write .Check that server/.env contains your project's values. Keep the App Certificate in the Go backend; the browser receives a signed token and does not need the certificate.
2. Configure the interview assistant
Before starting the app, open server/agent.go. Near the top, replace the existing const block containing adaPrompt and defaultGreeting with:
const (
adaPrompt = `You are Ada, a friendly interviewer helping a developer
practice discussing a software project in English, regardless of the
programming language used.Ask one question at a time and wait for the answer.
After each answer, point out one specific strength or one missing detail,
then ask a follow-up based on something the developer just said.
Focus on the problem, the developer's decisions, and what they learned.
Keep each turn to two or three short sentences suitable for speech.
If an answer is unclear, ask for clarification before evaluating it.
Treat this as practice, without assigning a hiring score.
`
defaultGreeting = "Hi! Let's practice talking about a project. What did you build, and what problem did it solve?"
)Keep the existing constant names. The starter passes adaPrompt into the agent's instructions and uses defaultGreeting for its opening message. The greeting gives the learner something specific to answer immediately; The instructions guide subsequent turns.
This exercise uses English because the supplied speech recognition configuration selects English. The recipe already configures managed Deepgram speech recognition, an OpenAI language model, and MiniMax speech output, so you don’t need to add separate provider API keys for this path.
3. Try a short interview
From the project root, start both services:
make devThis starts Gin on port 8000 and Next.js on port 3000. It also sets AGENT_BACKEND_URL=http://localhost:8000 for the frontend's API rewrites. Keep the terminal running.
Get June’s stories in your inbox
Join Medium for free to get updates from this writer.
Open http://localhost:3000, then:
- Click Start Conversation and allow microphone access.
- Listen for the interview greeting you just configured.
- Answer aloud. For example, “I built a small service that collects sensor readings. I used a queue so requests would not have to wait for processing.”
- Listen for one specific strength or missing detail in your answer, followed by a related question. For the example above, the agent might ask how you handled a growing queue. Check that your speech and the agent’s response appear in the transcript.
- Answer the follow-up, then click End Conversation.
The sensor-service answer is a practice example; use your own project if you have one. The agent’s exact response will vary. Check that its feedback refers to your answer and that it asks one question before waiting for you to speak.
Start another conversation to check that a new interview begins with the greeting. If you edit the Go instructions later, end the active conversation, stop the dev processes with Ctrl+C, run make dev again, and refresh the page. This starter runs go run . without a Go file watcher, so saving a file alone won't reload the backend.
4. How a conversation starts and ends
The browser talks to three API paths. Next.js rewrites them to handlers in server/main.go:
These requests control the conversation. Agora RTC carries the live audio between the browser and the cloud agent; RTM carries transcript and agent-state updates. Go doesn’t receive an HTTP request for each microphone audio chunk.
Starting a session
Inside server/agent.go, the service creates an authenticated SDK client using the backend credentials. It then builds an agent with your instructions, greeting, speech providers, and turn-detection settings.
The next step connects that configuration to a channel and its participants. Here is the existing session-start portion of the start method, shown for explanation; keep the surrounding implementation in place:
session := agent.CreateSession(agentkit.CreateSessionOptions{
Channel: channelName,
AgentUID: strconv.Itoa(agentUID),
RemoteUIDs: []string{strconv.Itoa(userUID)},
EnableStringUID: &enableStringUID,
IdleTimeout: &idleTimeout,
ExpiresIn: expiresIn,
})ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()agentID, err := session.Start(ctx)
if err != nil {
return nil, fmt.Errorf("start agent: %w", err)
}
Channel names the conversation. AgentUID identifies the agent participant, and RemoteUIDs selects the user it listens to. The agentID returned by Start identifies the running agent session for later lifecycle calls.
The Go context gives the startup call a 30-second deadline. Conversation duration is controlled separately through settings such as IdleTimeout and ExpiresIn. In the referenced starter, those are 30 seconds of idle time and a one-hour session expiry.
Ending a session
After startup, the backend retains the session under its agent ID. Clicking End Conversation sends { agentId } to the stop endpoint, where Go uses that ID to stop the session. The browser also logs out of RTM and clears its conversation state. You can read the full stop handling in server/agent.go.
End the conversation through the UI before stopping the local server so the app can send that explicit stop request.
Troubleshooting
If the app doesn’t start, check your local setup from the project root:
make doctor-localdoctor-local checks local prerequisites and whether the credential fields are configured. It doesn't make a live Agora call; a browser conversation is still needed to check microphone input and spoken replies.
If you later change backend routes or frontend API handling, the repository’s local verification guide covers the Go tests and checks using a fake backend. Those checks help find local wiring errors; they don’t test a real voice conversation.
Make the next practice round more specific
Once the interview works, change one instruction to focus on error handling. Ask Ada to follow up on what happens when part of the system fails. Restart the backend, begin a new conversation, and give the same sensor-service answer.
Listen for a question tied to that answer, such as what happens if processing fails after a reading enters the queue. If Ada moves to an unrelated interview question, revise the instruction and try again. This gives you a concrete check: does each follow-up build on what you just said?
Implementation reference: this tutorial follows the Go quickstart at revision d98ba88. The CLI may fetch a newer version; compare its files with that snapshot if paths or defaults differ.










