Project overview
The TEN Agent project is built on the TEN Framework and follows a modular architecture. This page describes the project structure, configuration system, and web server API.
TEN Agent uses a graph-based configuration system built on the TEN Framework concepts. The project organizes code into modular extensions that can be orchestrated through configuration files without modifying source code. The folder structure follows this pattern:
It contains the following important folders and files:
property.json
: This file contains the orchestration of extensions. It is the main runtime configuration file.ten_packages/extension
: This folder contains the extension modules. Each extension module is a separate Python/Golang/C++ package.server
: This folder contains the web server code. It is responsible for handling the incoming requests and start/stop of agent processes.playground
: This folder contains the UI code for the playground. It is a web-based interface to interact with the agent.
Runtime configuration
The main runtime configuration file is property.json
. It contains the orchestration of extensions. The file is structured as follows:
The file contains the following orchestration info:
- Graphs: Collections of nodes and connections that determine agent behavior
- Nodes: Individual extension instances with specific configurations
- Connections: Data flow paths between nodes
Graphs
The predefined_graphs
property contains a list of available graphs. Each graph defines how agent should behave in a specific scenario. Each graph Each graph contains:
name
: Unique identifier for the graphauto_start
: Whether to start this graph automaticallynodes
: List of extension instancesconnections
: Data routing between nodes
Nodes
The nodes
section contains the list of extensions that are part of the graph. Each node includes the following:
name
: Unique identifier of a node within the graphaddon
: Specifies the extension module to use You can create multiple instances of the same extension within a graph. For example, you might include severalchatgpt_openai_python
nodes, each using the sameaddon
property but with uniquename
properties. This allows you to run parallel instances of an extension with different configurations or behaviors.property
: Extension-specific configuration
Node Properties
The property
section of a node configures the extension's behavior. Each extension defines its available properties in the manifest.json
file within its folder. You can customize an extension by setting these runtime properties.
Read environment variables
Many extensions require API keys to function. Instead of hardcoding sensitive keys in property.json
, use environment variables with the syntax ${env:<env_var_name>|<default_value>}
. The following example shows how to read and use the OPENAI_API_KEY
environment variable:
Connections
The connections section defines how data flows between nodes. Each connection specifies:
- Source node: Identified by
extension_group
andextension
properties - Data protocols: Types of data that can flow:
audio_frame
,video_frame
,data
, orcmd
- Destinations: Where each data type is routed
For each protocol, you define destinations with:
name
: The data property keydest
: List of target nodes
The following example connects agora_rtc
extension to deepgram_asr
extension. The agora_rtc
extension sends pcm_frame
data to deepgram_asr
extension.
Extension folder
The ten_packages/extension
folder contains extension modules written in Python, Go, or C++. Each extension is a self-contained package with its own structure.
Extension folder names typically match the module name, though the definitive module name is specified in the extension's manifest.json
file. Use this module name as the addon
property value in your configuration.
The extension folder is structured as follows:
Extension common files
manifest.json
: Defines the extension's metadata including name, version, available properties, and supported APIs such asdata
,audio_frame
, andvideo_frame
property.json
: Specifies default configuration values for the extension
Extension-specific files
Each language has its own set of required files for extension development:
Language | Main logic file | Dependencies/Build file |
---|---|---|
Python | extension.py | requirements.txt : Python dependencies required by the extension. Dependencies are installed automatically when you run task use . |
Go | <name>_extension.go | go.mod : Go module definition that specifies the module name and dependencies. |
C++ | src/main.cc | BUILD.gn : Build configuration that specifies the target name and dependencies. |
The main logic file contains the core implementation of the extension for each language.
Web server
The Go-based web server manages agent processes and handles HTTP requests from clients. Both the playground and demo interfaces communicate with this server, though you can also interact directly using curl or any HTTP client.
API endpoints
The server exposes three endpoints for agent management:
- POST /start: Start an agent with specified configuration
- POST /stop: Stop a running agent
- POST /ping: Maintain agent connection
POST /start
Starts an agent with a specified graph and property overrides. The agent joins the specified RTC channel and subscribes to the user's audio stream.
Parameter | Description |
---|---|
request_id | UUID for request tracking |
channel_name | RTC channel name (must match the channel your client joins) |
user_uid | User's RTC identifier for audio subscription |
bot_uid | Optional agent RTC identifier |
graph_name | Graph configuration name from property.json |
properties | Property overrides (temporary, doesn't modify property.json ) |
timeout | Inactivity timeout in seconds (-1 disables timeout, default: 60s, configurable using WORKER_QUIT_TIMEOUT_SECONDS ) |
Example:
POST /stop
Stops a running agent instance.
Parameter | Description |
---|---|
request_id | UUID for request tracking |
channel_name | Channel name used when starting the agent |
Example:
POST /ping
Maintains the agent connection by sending a keepalive signal. Not required if the agent was started with timeout: -1
. Without pings, agents terminate after the configured timeout period.
Param | Description |
---|---|
request_id | UUID for request tracking |
channel_name | Channel name of the active agent |
Example: