Creating an agent

Agents are defined in a folder and synced using the CLI (or SDKs).

Text agent

The structure of the agent folder looks like this:

agents/support/
  agent.yaml
  instructions.md
  guardrail.md
  knowledge/returns.md
  skills/refund.md

The CLI makes it easy to create an agent folder

curl -fsSL https://getstream.io/cli/beta/install.sh | bash # the agents commands are in the beta CLI
getstream agents init my-agent --template text # or --template voice

agent.yaml sets up the agent's model selection, connectors, tool calling, MCP and so on.

agents/support/agent.yaml
name: support
mode: text
# the model to use, can reference a router or a model
llm: llm-fast
# connectors & MCP
connectors:
  - name: github
    connection: company # one GitHub account your app owns
    tools: [list_issues, get_*]

# if you need code execution
sandbox: daytona

connection: company is one GitHub account your app owns, so nobody signs in. Create it as in Shared account. See Connectors to let each user connect their own. tools limits which tools it offers; leave it out for all of them. Any other MCP server is a custom connector.

connectors is read by the CLI (beta).

llm can name a route from your LLM router or a provider/model.

instructions.md tells the agent what to do:

agents/support/instructions.md
You are Acme's support agent. Look up policies in your knowledge base before
answering. If someone asks for a refund, use the refund skill.

Try your agent using the CLI:

getstream agents test support --sync

guardrail.md aims to prevent your agent from answering questions it shouldn't. You don't want your support bot answering "why the sky is blue?", or "solve Navier-Stokes". It runs a decision model in parallel to the LLM response. Keep in mind that these tools never capture 100% of abuse. See Guardrails for blocking mode, thresholds and webhooks:

agents/support/guardrail.md
---
refusal: I can only help with questions about your Acme account and orders.
---

Answer questions about Acme products, orders, billing, shipping and returns.
Refuse anything else.

knowledge/ contains markdown files and URLs which are indexed. knowledge/urls.yaml allows you to index URLs. See Knowledge & skills. For more advanced use cases you can expand on this with tool calling.

agents/support/knowledge/returns.md
Items can be returned within 30 days of delivery for a full refund to the
original payment method. After 30 days, Acme offers store credit instead.
Opened headphones can only be returned if they are faulty.

skills/ make it easy to define a process for an agent. You could have a "refund" skill, or "package_tracking" or basically anything. Skills are the most important part of building a useful agent. See Skills for every option:

agents/support/skills/refund.md
---
description: work out whether a customer is owed a refund, and how much
---

Read the return policy and the order details the customer gave. Say whether
they are owed a refund, how much, and to which payment method. Two sentences
at most. If you need something only the customer knows, ask for it.

Sync your agent and talk to it:

getstream agents test support --sync

And for example ask: "What is your return policy?" to see the knowledge base answer, then "I bought headphones 40 days ago, can I get my money back?" to see the agent load the refund skill and follow it.

Voice agent

The approach for voice AI is just as straightforward. You can create a voice agent from the CLI like this

getstream agents init my-agent --template voice

Alternatively you can edit the agent.yaml for the agent you already have. The changes you want to make are:

  • Subagent: we use modern openAI style voice. The conversational/fast LLM hands of more complicated questions to the subagent. So you typically want a fast/ not so smart conversational model, and a slower/thinking subagent.
  • stt/tts: these can be set to a specific model or a router
  • greeting: how you say hi (text or variation mode)
  • keyterms: optionally terms that are common to your use case
agents/support/agent.yaml
name: support
mode: voice # joins a call
llm: llm-fast
subagent: llm-thinking
stt: en-low-latency # transcription
tts: en-low-latency # the voice it speaks with
greeting:
  text: Northwind Pizza, what can I get you?
  mode: variation # don't always say the exact same thing
keyterms: [Acme, store credit]
getstream agents test support --sync

To run on a native speech-to-speech model instead, name an sts route. It replaces stt, tts and llm:

agents/support/agent.yaml
name: support
mode: voice
sts: en-low-latency
subagent: llm-thinking

Other channels

The same agent can answer on other channels too:

See Connectors for everything else it can reach. To let it see, see Video.

Agent deep dive

To recap:

Path What it holds Learn more
agent.yaml What the agent runs on agent.yaml
instructions.md The system prompt
guardrail.md What it will and will not answer Guardrails
skills/*.md Workflows loaded when they are needed Knowledge & skills
knowledge/*.md What it may look things up in Knowledge & skills
knowledge/urls.yaml Pages the backend crawls into the knowledge base Adding URLs to knowledge
simulations/*.yaml Conversations to test it with Simulations & evals
.agent_sync Written by the sync: what was last synced, and when

Only agent.yaml is required

agent.yaml

Every key names a route or setting rather than hard-coding a model:

Key What it sets
name The config's name, which sessions are opened by. The CLI requires it; the SDKs fall back to the directory name.
description A note for whoever reads the config.
mode voice or text. A text agent needs no call and uses no speech routes. Defaults to voice.
llm The route or provider/model that holds the conversation. See LLM.
subagent Voice only: the route skills run on. When agent.yaml names none, the router defaults to llm-thinking when the deployment can route it, and the fast model answers everything itself when it cannot. A text agent runs its skills on its llm and is refused one. See Harness & sandbox.
stt, tts Transcription and voice routes for a cascade (transcribe, answer, speak). See STT and TTS.
sts A native speech-to-speech route. Naming one replaces stt, tts and llm.
voice The voice the agent speaks in, including a cloned one. See TTS.
greeting Said on joining without asking the model. Empty waits to be spoken to.
search The web search route the agent may use.
keyterms Words the transcriber should expect: names, products, jargon.
harness Which harness runs the agent. default is the only one.
sandbox daytona lets the agent run code: the subagent on a voice agent, the agent itself on a text agent. See Harness & sandbox.
connectors Connectors, including your own for any MCP server. See Connectors.
video source and max_frames (1 to 8) for an agent that looks at video. See Video.
tags Cost labels, so spend can be attributed to whatever they mean to you.
app Your application's own settings. Never sent to Stream, and the one place an unknown key is allowed.

Going further

To learn more about each feature: