# Create Agent Source: https://docs.trugen.ai/api-reference/endpoint/agentcreate POST /ext/agent Creates a new agent with avatar IDs, knowledge bases, and additional settings Create a new conversational video agent. Returns the agent's ID, which you'll use to embed the agent, mint session tokens, and manage it via the other endpoints. ## When to use * **First-time setup**: creating your first agent (or your first agent for a new use case) * **Programmatic rollouts**: creating many agents in bulk from your own workflows * **Testing**: spinning up experimental agents alongside your production ones If you're creating many similar agents, define a [template](/docs/agents/templates) once and use [Create Agent by Template](/api-reference/endpoint/agentcreatebytemplate) instead. ## Required fields At minimum you must send: * `agent_name`: used for display and identification * `agent_system_prompt`: how the agent should behave (see [Prompting Strategies](/docs/agents/prompting-strategies)) * `avatars[0].avatar_key_id`: the visual identity (from the [Avatar Gallery](/docs/avatars/gallery) or a custom avatar) Everything else falls back to platform defaults: * LLM: Groq `openai/gpt-oss-120b` * STT: Deepgram `deepgram/flux-general-en` * TTS: ElevenLabs `eleven_turbo_v2_5` with a default voice * Language: English * Turn detector: enabled * Max call duration: 300 seconds * Recording: disabled ## Minimum viable request ```bash theme={null} curl --request POST \ --url https://api.trugen.ai/v1/ext/agent \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data '{ "agent_name": "My First Agent", "agent_system_prompt": "You are a friendly assistant that answers in 1-2 sentences.", "avatars": [{ "avatar_key_id": "665a1170" }] }' ``` Response: ```json theme={null} { "id": "agt_12345example", "message": "Agent created successfully" } ``` ## Common gotchas * **`avatar_key_id` is not `agent_id`.** They look similar and it's an easy mixup. * **The prompt gets copied to `avatars[0].persona_prompt` under the hood.** For most agents the top-level `agent_system_prompt` is sufficient. * **Voices and LLMs have their own IDs.** Pick from the [Voice Library](/docs/agents/voices/library) and [Available LLMs](/docs/agents/available-llms). * **Setting `record: true` starts capturing recordings on the next session.** Confirm your privacy policy first. ## Next steps * [Embed the agent with the widget](/docs/integrations/widget-integration) * [Add a knowledge base](/docs/agents/knowledge/overview) * [Register tools](/docs/agents/tools/overview) * [Add guardrails](/docs/agents/guardrails/overview) * [Configure webhooks](/docs/agents/callback) # Create Agent By Template Source: https://docs.trugen.ai/api-reference/endpoint/agentcreatebytemplate POST /ext/agentbytemplate Create a new agent from a saved [template](/docs/agents/templates). The template supplies the shared configuration (prompt, knowledge, guardrails, LLM, TTS); you pass in the per-agent overrides (avatar, email, per-user context). ## Why templates Templates keep configuration consistent across many agents. If you run 50 agents that share the same behavior but differ in avatar and per-user context, define the behavior once as a template and spawn agents from it. The new agent inherits everything attached to the template, including its knowledge bases, tools, MCPs, and guardrails. You don't need to pass any of that again in this request. ## Required fields * `template_id`: the template to instantiate from * `avatar_key_id`: the visual identity for this specific agent ## Optional fields * `email`: used for [external meetings](/docs/agents/meetings/overview) as the meeting invite identity * `context_override`: inject per-agent context that will be appended to the shared system prompt ## Example ```bash theme={null} curl --request POST \ --url https://api.trugen.ai/v1/ext/agentbytemplate \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data '{ "template_id": "tpl_abc123", "avatar_key_id": "665a1170", "email": "priya@example.com", "context_override": "User is on the Growth plan, 30 seats, last ticket about SSO." }' ``` Response: ```json theme={null} { "id": "agt_98765example", "message": "Agent created successfully" } ``` ## Common patterns ### Per-customer rollout Loop over your customer list; for each customer, spin up a template-derived agent with per-customer context: ```typescript theme={null} for (const customer of customers) { await fetch("https://api.trugen.ai/v1/ext/agentbytemplate", { method: "POST", headers: { "x-api-key": process.env.TRUGEN_API_KEY!, "Content-Type": "application/json", }, body: JSON.stringify({ template_id: "tpl_customer_support", avatar_key_id: "665a1170", email: `support-${customer.slug}@meetings.trugen.ai`, context_override: `Customer: ${customer.name}. Plan: ${customer.plan}.`, }), }); } ``` ## Next steps * [Manage templates](/api-reference/endpoint/templatecreate) * [Templates concept](/docs/agents/templates) # Delete Agent Source: https://docs.trugen.ai/api-reference/endpoint/agentdelete DELETE /ext/agent/{id} Deletes a specific Agent permanently. # List All Agents Source: https://docs.trugen.ai/api-reference/endpoint/agentget GET /ext/agent Fetches a list of all your agents, including associated avatars, knowledge bases, and callback settings. # Get Agent By Id Source: https://docs.trugen.ai/api-reference/endpoint/agentgetbyid GET /ext/agent/{id} Retrieve an Agent by ID Fetch the complete configuration for a single agent by ID. Useful for auditing, debugging, cloning, or building admin UIs on top of TruGen. ## When to use * **Debugging**: confirm the live configuration matches what you think it is * **Cloning**: read a working agent, tweak, and re-create as a new agent * **Admin dashboards**: build an internal view of your organization's agents * **Backup**: snapshot configuration before making changes ## What's returned The full agent object as it exists on the server, including: * Top-level fields (`agent_name`, `agent_system_prompt`, `is_active`, `record`, `callback_url`, etc.) * All configured avatars with STT, LLM, TTS, and turn-detection settings * Attached knowledge bases (by ID) * Attached tools and MCPs (by ID) * Attached guardrails (full objects: `key`, `category`, `prompt`, `response_message`, `callback_url`) * Widget configuration ## Common gotchas * **The response can be large.** Agents with many avatars, tools, and knowledge bases produce sizable responses. Cache aggressively on your side. * **Attachments are returned as IDs.** Attached tools, knowledge bases, and MCPs are returned as IDs: fetch the individual resources separately if you need their full configuration. * **Not found returns 404.** If the agent was deleted, the endpoint returns 404. ## Next steps * [List all agents](/api-reference/endpoint/agentget) * [Update the agent](/api-reference/endpoint/agentupdate) * [Delete the agent](/api-reference/endpoint/agentdelete) # Update Agent Source: https://docs.trugen.ai/api-reference/endpoint/agentupdate PUT /ext/agent/{id} Updates an Agent with new avatar, knowledge base, or system settings. Replace an agent's configuration. `PUT` is a full-replace: send the complete configuration, not a partial. For partial updates, use `PATCH /ext/agent/{id}`. ## When to use PUT vs PATCH | Endpoint | Behavior | Use when | | - | - | - | | `PUT /ext/agent/{id}` | Full replace: omitted fields reset to defaults | You want to re-declare the full agent state | | `PATCH /ext/agent/{id}` | Partial merge: only send changed fields | You want to update one field without touching others | ## Effect on live sessions Updates take effect on the **next session**: existing active sessions keep the previous configuration until they end. If you need to force a config change immediately, end active sessions with [`DELETE /v1/conversation/{conversationId}`](/api-reference/endpoint/conversationdelete) after the update lands. ## Common patterns ### Change the prompt without touching anything else ```bash theme={null} curl --request PATCH \ --url https://api.trugen.ai/v1/ext/agent/{id} \ --header 'x-api-key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "agent_system_prompt": "You are Priya, a friendly nutritionist AI…" }' ``` ### Swap the LLM provider ```bash theme={null} curl --request PATCH \ --url https://api.trugen.ai/v1/ext/agent/{id} \ --header 'x-api-key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "avatars": [ { "llm": { "provider": "groq", "model": "openai/gpt-oss-120b", "fallback_model": "gpt-5.4-mini" } } ] }' ``` ### Deactivate without deleting ```bash theme={null} curl --request PATCH \ --url https://api.trugen.ai/v1/ext/agent/{id} \ --header 'x-api-key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "is_active": false }' ``` ## Next steps * [Retrieve the current agent](/api-reference/endpoint/agentgetbyid) * [Delete an agent](/api-reference/endpoint/agentdelete) # List All Avatars Source: https://docs.trugen.ai/api-reference/endpoint/avatarget GET /ext/avatars Fetch a list of stock avatars that are available to be used as the face for your agents. # Delete Conversation Source: https://docs.trugen.ai/api-reference/endpoint/conversationdelete DELETE /v1/conversation/{conversation_id} End an ongoing conversation session. # List All Conversations Source: https://docs.trugen.ai/api-reference/endpoint/conversationget GET /ext/conversation Retrieve all Conversations with all fields and optional pagination/filtering. # Get Conversation By Id Source: https://docs.trugen.ai/api-reference/endpoint/conversationgetbyid GET /ext/conversation/{id} # Speak Source: https://docs.trugen.ai/api-reference/endpoint/conversationspeak PUT /v1/conversation/{conversation_id}/speak Send a text message to an active conversation and the agent will speak it aloud. Make the agent speak arbitrary text mid-conversation. Overrides whatever the agent was about to say. Use for scripted interjections, custom greetings, or human-in-the-loop takeover. ## When to use * **Human handoff**: a live agent takes over and needs to say a specific thing * **System notifications**: announce something the LLM shouldn't have to reason about ("Your call is being transferred…") * **Custom greetings**: inject a personalized greeting the LLM might otherwise phrase awkwardly * **Scripted flows**: force the agent to say a specific line at a specific point in a structured workflow ## What it does The current LLM turn (if any) is interrupted. The text you supply is sent straight to TTS and the avatar renders it. After the utterance completes, the LLM regains control on the user's next turn. ## Example ```bash theme={null} curl --request PUT \ --url https://api.trugen.ai/v1/conversation/{conversation_id}/speak \ --header 'x-api-key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "text": "One moment while I transfer you to a human agent.", "interrupt": true }' ``` ## Interrupt behavior | `interrupt` | Effect | | - | - | | `true` (default) | Cut off any current agent utterance; speak the new text immediately | | `false` | Wait for the current utterance to finish, then speak the new text | ## Add context afterwards If you want the LLM to know it just said something outside its usual turn: ```json theme={null} { "text": "One moment while I transfer you.", "interrupt": true, "add_to_context": true } ``` With `add_to_context: true`, the utterance is added to the LLM's message history so it can reason about what was said. ## Common uses ### Trigger a personalized greeting ```typescript theme={null} // After session starts, before the agent's default greeting await fetch( `https://api.trugen.ai/v1/conversation/${conversationId}/speak`, { method: "PUT", headers: { "x-api-key": KEY, "Content-Type": "application/json" }, body: JSON.stringify({ text: `Hi ${userName}, good to see you back. Last time you were asking about ${lastTopic}: where do you want to pick up?`, interrupt: true, }), } ); ``` ### Announce transfer to human ```json theme={null} { "text": "Let me connect you with Alex from our team. Please hold for a moment.", "interrupt": true, "add_to_context": true } ``` ## Next steps * [End the conversation](/api-reference/endpoint/conversationdelete) * [Get conversation by ID](/api-reference/endpoint/conversationgetbyid) # Create Custom Avatar Source: https://docs.trugen.ai/api-reference/endpoint/customavatarcreate POST /v2/custom-avatar Submits a custom avatar generation job from a base64-encoded source image. Requires `x-api-key` authentication. # Delete Custom Avatar Source: https://docs.trugen.ai/api-reference/endpoint/customavatardelete DELETE /v2/custom-avatar/{id} Deletes a custom avatar owned by the caller. Requires `x-api-key` authentication. # Get Custom Avatar Source: https://docs.trugen.ai/api-reference/endpoint/customavatargetbyid GET /v2/custom-avatar/{id} Fetch a single custom avatar by its internal `id`. Use this to poll a job's `status` until it becomes `COMPLETED`. Requires `x-api-key` authentication. # Join External Meeting Source: https://docs.trugen.ai/api-reference/endpoint/externalmeeting POST /ext/externalmeeting Send a TruGen agent into a live external meeting (Google Meet, Zoom, Microsoft Teams). The agent joins as a participant, listens, speaks, and captures a full transcript. Requires `x-api-key` authentication. # Create Guardrail Source: https://docs.trugen.ai/api-reference/endpoint/guardrailcreate POST /ext/guardrail Creates a new guardrail rule for use within the TruGen AI system. Guardrails are workspace-scoped and reusable across agents - creating one does not attach it anywhere. # Delete Guardrail Source: https://docs.trugen.ai/api-reference/endpoint/guardraildelete DELETE /ext/guardrail/{id} Deletes a guardrail by its unique ID. Deletion does not cascade - if the guardrail is still attached to one or more agents, the attachment reference is left dangling. It's excluded automatically at runtime (harmless), but not cleaned up. Detach it first if you want a clean state. # List All Guardrails Source: https://docs.trugen.ai/api-reference/endpoint/guardrailget GET /ext/guardrail Fetches all guardrails in your workspace. Requires `x-api-key` authentication. # Update Guardrail Source: https://docs.trugen.ai/api-reference/endpoint/guardrailupdate PUT /ext/guardrail/{id} Replaces an existing guardrail's configuration by its unique ID. This is a full replace of every client-settable field, not a partial patch. `key` is never changed by an update, even if `name` changes. # Add Documents to Knowledge Base Source: https://docs.trugen.ai/api-reference/endpoint/knowledgebaseadddoc POST /ext/kb/{id}/doc Uploads additional content or a document to an existing Knowledge Base. Requires `x-api-key` authentication. Add a document to an existing [knowledge base](/docs/agents/knowledge/overview). Supported formats: **PDF**, **DOCX**, **DOC**, **TXT**, **PPTX**, **PNG**, **JPG**, **JPEG**, **MD**, **JSON**, plain text, and URLs (single page or full site crawl). ## Supported inputs | Input | Content-Type | Notes | | - | - | - | | Document file (`.pdf`, `.docx`, `.doc`, `.txt`, `.pptx`, `.png`, `.jpg`, `.jpeg`, `.md`, `.json`) | `multipart/form-data` | Best for policies, manuals, images, structured content | | Plain text | `multipart/form-data` or JSON | For FAQs and scripted content | | Single URL | JSON | TruGen fetches, parses, and indexes the page | | Root URL (crawl) | JSON | TruGen crawls the site up to N pages deep | ## Upload a file ```bash theme={null} curl --request POST \ --url https://api.trugen.ai/v1/ext/kb/{id}/doc \ --header 'x-api-key: YOUR_API_KEY' \ --form 'file=@/path/to/product-guide.pdf' ``` ## Upload from a URL ```bash theme={null} curl --request POST \ --url https://api.trugen.ai/v1/ext/kb/{id}/doc \ --header 'x-api-key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "type": "url", "url": "https://docs.yourcompany.com/pricing" }' ``` To crawl an entire site: ```json theme={null} { "type": "url", "url": "https://docs.yourcompany.com", "crawl": true, "max_pages": 100 } ``` ## Response ```json theme={null} { "doc_id": "doc_abc123", "status": "processing", "message": "Document accepted; indexing in progress" } ``` ## Indexing status Documents pass through: `queued` → `processing` → `ready` (or `failed`). Poll the parent KB to see all documents' status: ``` GET /ext/kb/{id} ``` ## Best practices * **Clean text beats fancy PDFs.** A PDF with unusual layouts, footnotes, or tables retrieves poorly. Convert to Markdown when you can. * **Split large documents.** A 100-page PDF retrieves worse than 10 well-scoped documents. * **Use titles that describe content.** File names show up in retrieval reasoning; `hr-leave-policy-2026.pdf` beats `document-final-v2.pdf`. * **Re-upload changed docs rather than editing.** Delete the old one and upload the new one for a clean index. ## Common failures * **`unsupported_format`**: the file isn't a PDF, DOCX, or text. * **`file_too_large`**: max 50 MB per file. Split larger files. * **`crawl_failed`**: the target URL rejected our crawler (robots.txt, auth-gated, JS-only). Provide static, publicly reachable URLs. * **`extraction_low_confidence`**: the document was successfully processed but content quality is low. Common with heavily-formatted PDFs. ## Next steps * [Delete a document](/api-reference/endpoint/knowledgebasedeletedoc) * [Update the KB](/api-reference/endpoint/knowledgebaseupdate) * [Knowledge Base concepts](/docs/agents/knowledge/overview) # Create Knowledge Base Source: https://docs.trugen.ai/api-reference/endpoint/knowledgebasecreate POST /ext/kb Uploads a document or raw text to create a new Knowledge Base entry. Requires `x-api-key` authentication. Create a new [knowledge base](/docs/agents/knowledge/overview): a collection of documents your agents search when they need to ground an answer in your data. ## When to create a new knowledge base Create separate knowledge bases per **domain**, not per document. Small, well-scoped KBs retrieve dramatically better than one large mixed KB. **Good scoping:** * `Product-Docs`: product features, setup, integrations * `Pricing-and-Plans`: pricing, plan differences, discounts * `Support-FAQs`: common troubleshooting **Bad scoping:** * `All-Company-Docs`: the LLM can't tell what's in it, so retrieval quality drops ## Name and description matter The `name` and `description` are how the agent decides whether to search this knowledge base. Be specific. ```json theme={null} { "name": "HR-Policies", "description": "Use this whenever the user asks about HR policies, leave entitlements, benefits, or employee guidelines." } ``` The description especially: the LLM reads it verbatim when deciding routing. ## Example ```bash theme={null} curl --request POST \ --url https://api.trugen.ai/v1/ext/kb \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data '{ "name": "Product-Docs", "description": "Use this when the user asks about product features, setup instructions, integrations, or technical specifications.", "is_active": true }' ``` Response: ```json theme={null} { "id": "kb_prod_docs_123", "message": "Knowledge base created successfully" } ``` ## Next steps Once the KB is created, add documents: ``` POST /ext/kb/{id}/doc ``` See [Add Document](/api-reference/endpoint/knowledgebaseadddoc) for the file upload flow. Then attach the KB to an agent: ```json theme={null} "knowledge_base": [ { "id": "kb_prod_docs_123", "name": "Product-Docs" } ] ``` # Delete Knowledge Base Source: https://docs.trugen.ai/api-reference/endpoint/knowledgebasedelete DELETE /ext/kb/{id} Deletes a Knowledge Base by ID. Requires `x-api-key` authentication. # Delete Document from Knowledge Base Source: https://docs.trugen.ai/api-reference/endpoint/knowledgebasedeletedoc DELETE /ext/kb/doc/{id} Deletes a specific document from an existing Knowledge Base using its document ID. # List All Knowledge Bases Source: https://docs.trugen.ai/api-reference/endpoint/knowledgebaseget GET /ext/kbs Fetches a list of all available knowledge bases with their metadata and associated documents. # Get Knowledge Base By Id Source: https://docs.trugen.ai/api-reference/endpoint/knowledgebasegetbyid GET /ext/kb/{id} Retrieves a specific knowledge base and its associated documents using the provided Knowledge Base ID. Requires `x-api-key` authentication. # Update Knowledge Base Source: https://docs.trugen.ai/api-reference/endpoint/knowledgebaseupdate PUT /ext/kb/{id} Update name and description of a specific Knowledge Base by ID. Requires `x-api-key` authentication. # Create MCP Source: https://docs.trugen.ai/api-reference/endpoint/mcpcreate POST /ext/mcp Create a new MCP server configuration. # Delete MCP Source: https://docs.trugen.ai/api-reference/endpoint/mcpdelete DELETE /ext/mcp/{id} Deletes an MCP details by its ID. Requires `x-api-key` authentication. # List All MCPs Source: https://docs.trugen.ai/api-reference/endpoint/mcpget GET /ext/mcp Fetches a list of available MCP configurations. Requires `x-api-key` authentication. # Get MCP By Id Source: https://docs.trugen.ai/api-reference/endpoint/mcpgetbyid GET /ext/mcp/{id} Fetch a single MCP configuration by its unique ID. Requires `x-api-key` authentication. # Update MCP Source: https://docs.trugen.ai/api-reference/endpoint/mcpupdate PUT /ext/mcp/{id} Updates an existing MCP configuration by its ID. Requires `x-api-key` authentication. # Upload Presentation Source: https://docs.trugen.ai/api-reference/endpoint/presentationcreate POST /ext/presentation Upload a presentation deck (`.pdf` or `.pptx`) to your library. When attached to an agent, the agent semantically searches the deck to present matching slides visually during live conversations. Upload a presentation deck (`.pdf` or `.pptx`) to your library. When attached to an agent, the agent semantically searches the deck to present matching slides visually during live conversations. ## When to upload a presentation Upload visual slide decks for content that requires visual demonstration alongside spoken explanations: * **Sales & Pitch Decks**: product feature decks, pricing slides, competitive comparisons * **Architecture & Technical Diagrams**: system architecture, data flow diagrams, technical setup * **Tutorials & Product Demos**: step-by-step onboarding slides, feature walkthroughs ## Supported formats & size limits | Media | Formats | Max Size | Processing Notes | | - | - | - | - | | **PDF** | `.pdf` | **100 MB** | Extracted page-by-page into slide images and indexed. | | **PowerPoint** | `.pptx` | **100 MB** | Extracted slide-by-slide and indexed for semantic search. | ## Required fields * `name`: a clear, descriptive title for the presentation deck * `input`: the `.pdf` or `.pptx` presentation file (`multipart/form-data`) ## Optional fields * `description`: detailed summary explaining when the agent should select this presentation deck ## Example ```bash theme={null} curl --request POST \ --url https://api.trugen.ai/v1/ext/presentation \ --header 'x-api-key: YOUR_API_KEY' \ --form 'name="Q3 Sales Deck"' \ --form 'description="Quarterly sales presentation for 2025"' \ --form 'input=@/path/to/presentation.pdf' ``` Response: ```json theme={null} { "id": "1411f164-fe94-4a4b-9b1b-027a9929f95d", "message": "Presentation uploaded successfully" } ``` ## Next steps After uploading, attach the presentation to an agent via the `visual_presentations` array: ```json theme={null} "visual_presentations": [ { "id": "1411f164-fe94-4a4b-9b1b-027a9929f95d" } ] ``` See [Attaching to Agents](/docs/presentations/attaching) for detailed setup. # Delete Presentation Source: https://docs.trugen.ai/api-reference/endpoint/presentationdelete DELETE /ext/presentation/{id} Delete a presentation deck permanently from your workspace library. Delete a presentation deck permanently from your workspace library. ## Effects of deletion Deleting a presentation immediately removes all stored slides and indexed embeddings. Any active or future agent sessions referencing this presentation will no longer present slides from this deck. ## Parameters * `id` (path, required): unique identifier of the presentation to delete ## Example ```bash theme={null} curl --request DELETE \ --url https://api.trugen.ai/v1/ext/presentation/1411f164-fe94-4a4b-9b1b-027a9929f95d \ --header 'x-api-key: YOUR_API_KEY' ``` Response: ```json theme={null} { "deleted": true, "id": "1411f164-fe94-4a4b-9b1b-027a9929f95d", "presentation_id": "4c42df84-f6f4-4f77-8d6c-124ad83df8bb" } ``` # List All Presentations Source: https://docs.trugen.ai/api-reference/endpoint/presentationget GET /ext/presentation Retrieve all presentation decks available in your project workspace, including their resource details, page count, preview URLs, and processing status. Retrieve all presentation decks available in your project workspace, including their resource details, page count, preview URLs, and processing status. ## Response Fields * `id`: unique identifier of the presentation deck * `name`: title of the presentation * `status`: current processing state (`pending`, `processing`, `completed`, `failed`) * `resources`: array of uploaded document resources and preview links * `id`: resource UUID * `name`: original file name * `page_count`: total number of slides/pages extracted * `preview_url`: temporary signed S3 URL to preview the document * `status`: resource processing status ## Example ```bash theme={null} curl --request GET \ --url https://api.trugen.ai/v1/ext/presentation \ --header 'x-api-key: YOUR_API_KEY' ``` Response: ```json theme={null} [ { "created_at": "2026-09-04T12:36:51.773302Z", "id": "b3a3bc93-6b37-496e-989d-cf793792f428", "name": "Q3 Sales Deck", "resources": [ { "created_at": "2026-09-04T12:36:51.773302Z", "description": "Quarterly sales presentation for 2025", "id": "65459261-d946-4889-9528-610e0770162d", "name": "R Parthieshwar Resume.pdf", "page_count": 2, "preview_url": "https://trugen-agents-presentations-docs.s3.us-east-2.amazonaws.com/qaapp.trugen.ai/uploads/input/b3a3bc93-6b37-496e-989d-cf793792f428/65459261-d946-4889-9528-610e0770162d/R%20Parthieshwar%20Resume.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Checksum-Mode=ENABLED&X-Amz-Credential=AKIAY2F3GNLRMROY7MOZ%2F20260904%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Date=20260904T123707Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&response-content-disposition=inline&response-content-type=application%2Fpdf&x-id=GetObject&X-Amz-Signature=e5fa6e304478c9803aa573bfd29aa1c57cff762438c34754352db57648f85e24", "status": "processing", "updated_at": "2026-09-04T12:37:02.030418Z" } ], "status": "pending", "updated_at": "2026-09-04T12:36:51.773302Z" } ] ``` # Get Presentation Source: https://docs.trugen.ai/api-reference/endpoint/presentationgetbyid GET /ext/presentation/{id} Fetch a single presentation deck by its unique ID. Returns metadata, processing status, and resource preview links. Fetch a single presentation deck by its unique ID. Returns metadata, processing status, and resource preview links. ## Parameters * `id` (path, required): unique identifier of the presentation deck ## Example ```bash theme={null} curl --request GET \ --url https://api.trugen.ai/v1/ext/presentation/b3a3bc93-6b37-496e-989d-cf793792f428 \ --header 'x-api-key: YOUR_API_KEY' ``` Response: ```json theme={null} { "created_at": "2026-09-04T12:36:51.773302Z", "id": "b3a3bc93-6b37-496e-989d-cf793792f428", "name": "Q3 Sales Deck", "resources": [ { "created_at": "2026-09-04T12:36:51.773302Z", "description": "Quarterly sales presentation for 2025", "id": "65459261-d946-4889-9528-610e0770162d", "name": "R Parthieshwar Resume.pdf", "page_count": 2, "preview_url": "https://trugen-agents-presentations-docs.s3.us-east-2.amazonaws.com/qaapp.trugen.ai/uploads/input/b3a3bc93-6b37-496e-989d-cf793792f428/65459261-d946-4889-9528-610e0770162d/R%20Parthieshwar%20Resume.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Checksum-Mode=ENABLED&X-Amz-Credential=AKIAY2F3GNLRMROY7MOZ%2F20260904%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Date=20260904T123707Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&response-content-disposition=inline&response-content-type=application%2Fpdf&x-id=GetObject&X-Amz-Signature=e5fa6e304478c9803aa573bfd29aa1c57cff762438c34754352db57648f85e24", "status": "processing", "updated_at": "2026-09-04T12:37:02.030418Z" } ], "status": "pending", "updated_at": "2026-09-04T12:36:51.773302Z" } ``` # Update Presentation Source: https://docs.trugen.ai/api-reference/endpoint/presentationupdate PATCH /ext/presentation/{id} Update the metadata (such as description) of an existing presentation deck. Update the metadata (such as description) of an existing presentation deck. ## When to update Update presentation details when you want to refine the description so the agent better understands when to trigger and present slides from this deck during user queries. ## Parameters * `id` (path, required): unique identifier of the presentation ## Request Body * `description` (string, optional): updated description detailing the topics covered in the deck ## Example ```bash theme={null} curl --request PATCH \ --url https://api.trugen.ai/v1/ext/presentation/1411f164-fe94-4a4b-9b1b-027a9929f95d \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data '{ "description": "Updated sales pitch deck for Q3 & Q4" }' ``` Response: ```json theme={null} { "id": "1411f164-fe94-4a4b-9b1b-027a9929f95d", "message": "Presentation details updated" } ``` ## Next steps * [Get presentation status](/api-reference/endpoint/presentationgetbyid) * [Visual Presentations concepts](/docs/presentations/overview) # List All Providers Source: https://docs.trugen.ai/api-reference/endpoint/providerget GET /ext/providers Fetch a list of all available providers and their supported models. Fetch a list of all available providers and their supported models across LLM, TTS, STT, and Avatar services. ## Overview Use this endpoint to inspect the available providers and models in your project workspace programmatically. ## Example ```bash theme={null} curl --request GET \ --url https://api.trugen.ai/v1/ext/providers \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' ``` ## Response Returns a JSON dictionary of supported providers and model categories. # List All Sessions Source: https://docs.trugen.ai/api-reference/endpoint/sessionget GET /ext/sessions Retrieve all your sessions with their current status. # Create Persona Template Source: https://docs.trugen.ai/api-reference/endpoint/templatecreate POST /ext/template Creates a new template. Create a reusable [template](/docs/agents/templates): the shared configuration that many agents can derive from. Use templates to enforce consistent behavior across a fleet of agents. ## What belongs in a template * The shared system prompt * Attached knowledge bases * Attached guardrails * LLM, STT, TTS configuration * Default avatar (individual agents can override) * Callback configuration ## What doesn't * Per-user or per-agent identifiers (avatar assignments, meeting emails, agent names) * Runtime session data ## Example ```bash theme={null} curl --request POST \ --url https://api.trugen.ai/v1/ext/template \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data '{ "template_name": "Customer Support Template", "template_system_prompt": "You are a friendly support agent. Answer in 1-2 sentences and always confirm before taking action.", "config": { "timeout": 300, "conversationalContext": "support" }, "knowledge_base": [ { "id": "kb_prod_docs", "name": "Product Docs" }, { "id": "kb_faqs", "name": "FAQs" } ], "guardrail": [ { "id": "grd_hate_speech", "name": "Hate Speech Filter" } ], "is_active": true, "record": true }' ``` Response: ```json theme={null} { "id": "tpl_abc123", "message": "Template created successfully" } ``` ## Using the template Once created, spin up agents from it with [Create Agent by Template](/api-reference/endpoint/agentcreatebytemplate). ## Next steps * [List templates](/api-reference/endpoint/templateget) * [Update template](/api-reference/endpoint/templateupdate) * [Templates concept](/docs/agents/templates) # Delete Persona Template Source: https://docs.trugen.ai/api-reference/endpoint/templatedelete DELETE /ext/template/{id} # List All Persona Templates Source: https://docs.trugen.ai/api-reference/endpoint/templateget GET /ext/templates Fetches a list of all templates. # Get Persona Template By Id Source: https://docs.trugen.ai/api-reference/endpoint/templategetbyid GET /ext/template/{id} # Update Persona Template Source: https://docs.trugen.ai/api-reference/endpoint/templateupdate PUT /ext/template/{id} Updates the details of a specific template by ID. # Text To Video Generator Source: https://docs.trugen.ai/api-reference/endpoint/texttovideo POST /script-to-video/createVideo Generate a real life avatar video from text. Provide a script along with an avatar, voice, and provider configuration to produce a rendered video. The response returns a `generation_id` which can be used to track the status of the video generation. # Get Generation Status Source: https://docs.trugen.ai/api-reference/endpoint/texttovideostatus GET /script-to-video/genStatus/{generation_id} Retrieve the current status and details of a video generation job using its `generation_id`. # Create Tool Source: https://docs.trugen.ai/api-reference/endpoint/toolcreate POST /ext/tool Creates a new tool details for use within the Trugen AI system. # Delete Tool Source: https://docs.trugen.ai/api-reference/endpoint/tooldelete DELETE /ext/tool/{id} Deletes a tool details by its unique ID. # List All Tools Source: https://docs.trugen.ai/api-reference/endpoint/toolget GET /ext/tool Fetches all tool details available in the system. Requires `x-api-key` authentication. # Get Tool By Id Source: https://docs.trugen.ai/api-reference/endpoint/toolgetbyid GET /ext/tool/{id} Fetches a specific tool details using its unique ID. Requires `x-api-key` authentication. # Update Tool Source: https://docs.trugen.ai/api-reference/endpoint/toolupdate PUT /ext/tool/{id} Updates an existing client-side tool using its unique ID. # Start Vision Session Source: https://docs.trugen.ai/api-reference/endpoint/visionstart POST /v2/vision Attach Hawkeye-1 to a LiveKit room and begin real-time video analysis. Hawkeye joins as a subscriber, analyses the target participant's video, and streams alerts to your callback URL whenever a chosen class is detected. Billed at 1¢/minute. Requires `x-api-key` authentication. # Get Vision Session Source: https://docs.trugen.ai/api-reference/endpoint/visionstatus GET /v2/vision/{session_id} Fetch the current state of a Hawkeye vision session: queued, running, or ended. Each call refreshes from Hawkeye, so you always get the latest status. Requires `x-api-key` authentication. # API Overview Source: https://docs.trugen.ai/api-reference/overview Server-to-server REST API for creating and managing TruGen agents, sessions, and knowledge. The TruGen REST API is how you programmatically create agents, manage templates, ground them in your data, register tools, and read session records. Everything you can do in the [Developer Portal](https://app.trugen.ai), you can do here. ## Base URL ``` https://api.trugen.ai/v1 ``` All responses are `application/json` unless otherwise noted. ## Authentication Every request must include an `X-API-Key` header. Create keys in the [Developer Portal](https://app.trugen.ai/api-keys). ```bash theme={null} curl https://api.trugen.ai/v1/ext/agent \ --header 'X-API-Key: YOUR_API_KEY' ``` Your API key is server-only. Never embed it in browser or mobile client code. For client-side use, exchange the API key for a short-lived session token via the [JS SDK Authentication](/docs/sdks/javascript/authentication) or [Python SDK Authentication](/docs/sdks/python/authentication) flow. ## Two-tier authentication model TruGen uses two credentials, each with a different purpose: | Credential | Where it lives | What it can do | | - | - | - | | **API Key** | Your server (`X-API-Key` header) | Every REST endpoint. Create agents, manage templates, read conversations. | | **Session Token** | Passed to the browser | Join one live conversation. | See [JS SDK Authentication](/docs/sdks/javascript/authentication) or [Python SDK Authentication](/docs/sdks/python/authentication) for the full pattern. ## Resource model The API is organized around a small set of resources: | Resource | Purpose | | - | - | | **Agents** | The primary object: a configured conversational video agent with a prompt, avatar, voice, LLM, and tools | | **Templates** | Reusable blueprints: share prompt, knowledge, and behavior across many agents | | **Knowledge Bases** | Document collections your agents ground answers in via RAG | | **Tools** | Callable actions your agents invoke during conversations (webhooks, MCP, integrations, client actions) | | **Guardrails** | Safety-check rules your agents can call as a tool: canned responses, moderation checks, and trigger webhooks | | **MCPs** | Model Context Protocol server configurations | | **Providers** | The set of LLM, STT, and TTS providers available in your environment | | **Avatars** | Visual identities: stock or custom | | **Conversations** | Session records: including full chat history, feedback, and usage | | **Sessions** | Live session records: status, avatar, and room info for every session | ## Common patterns ### Create an agent → embed it 1. `POST /v1/ext/agent`: create the agent, get an `agent_id` 2. Drop the [widget](/docs/integrations/widget-integration) or [iframe](/docs/integrations/embed-via-iFrame) with that ID 3. Users interact: sessions are automatically tracked ### Personalize per user 1. Create an agent once with the shared prompt 2. On each session, mint a session token with `userId`, `userName`, and `context` 3. The agent sees this context and personalizes accordingly ### Use a template across many agents 1. `POST /v1/ext/template`: create the template with the shared config 2. `POST /v1/ext/agentbytemplate`: spin up a new agent from the template ### Access session results 1. Handle the `call_ended` webhook: see [Event Callbacks](/docs/agents/callback) 2. Fetch the conversation record with [`GET /v1/ext/conversation/{id}`](/api-reference/endpoint/conversationgetbyid): includes `chat_history`, `snippets`, `feedback`, `usage_json` ## Errors Errors are returned as JSON with an `error` field: ```json theme={null} { "error": "Unauthorized: not a valid authorization api key" } ``` ## Pagination List endpoints use `offset` + `perpage` query parameters: ``` GET /v1/ext/conversation?offset=0&perpage=20 ``` The response includes an `X-Total-Count` header with the total match count for the query. Additional filters vary per endpoint: check the individual endpoint page. ## Versioning The API is versioned in the URL path (`/v1/…`, `/v2/…`). Breaking changes ship as new versions. Non-breaking additions ship in place; watch the [changelog](/docs/changelog) for notice. ## Documentation map Create, fetch, update, and delete conversational agents. Reusable persona blueprints. Ground answers in your documents and URLs. Session records, transcripts, and speak commands. Browse all your past and current sessions. Register callable actions for agents. Safety-check rules agents can call mid-conversation. List available STT, LLM, and TTS providers. Browse stock and custom avatars. Async video generation from a script. Each endpoint page includes the full request/response schema, an example, and cross-links to related concepts. ## Quick links * **[JS SDK Authentication](/docs/sdks/javascript/authentication)**: client-safe token exchange * **[Callbacks](/docs/agents/callback)**: real-time event webhooks # Available LLMs Source: https://docs.trugen.ai/docs/agents/available-llms All large language models available on TruGen, organised by provider. The LLM is the reasoning engine behind every AI Teammate. When a user speaks, their words are transcribed by the STT engine and passed to the LLM, which generates the response that the TTS engine then speaks aloud. Choosing the right model affects response quality, latency, and cost. TruGen supports a range of models across multiple providers, so you can optimise for speed, quality, cost, or compliance depending on your use case. You can also connect your own LLM: see [Bring Your Own LLM](/docs/resources/byo-llm). Use the `/v1/providers` endpoint to always fetch the latest available model list. *** ## Groq Ultra-low latency inference. Best for real-time conversational agents where response speed and throughput are top priorities. | Model | Model ID | Provider Key | Description | | - | - | - | - | | **GPT OSS 20b** | `openai/gpt-oss-20b` | `groq` | Extremely fast, high-throughput reasoning model. By OpenAI. | | **GPT OSS 120b** | `openai/gpt-oss-120b` | `groq` | Fast, high-throughput OpenAI GPT reasoning model, great at tool calling. By OpenAI. | *** ## OpenAI High-performance models for agentic and multimodal workflows. | Model | Model ID | Provider Key | Description | | - | - | - | - | | **GPT 5.4 Mini** | `openai/gpt-5.4-mini` | `lk-inference` | Built for agentic workflows, fast latency, and excels in multimodal tasks. By OpenAI. | *** ## Google Gemini and Gemma models optimized for reasoning, communication, and efficiency. | Model | Model ID | Provider Key | Description | | - | - | - | - | | **Gemini 4 31b** | `google/gemma-4-31b-it` | `lk-inference` | Best for advanced reasoning, multimodal understanding, and agentic workflows. By Gemini. | | **Gemini 3.5 Flash Lite** | `google/gemini-3.5-flash-lite` | `lk-inference` | Built for fast and efficient AI workflows. By Gemini. | | **Gemini 3.1 Flash Lite** | `google/gemini-3.1-flash-lite` | `lk-inference` | Built for communication. By Gemini. | *** ## Kimi Advanced multimodal models designed for autonomous agents. | Model | Model ID | Provider Key | Description | | - | - | - | - | | **Kimi K2.6** | `moonshotai/kimi-k2.6` | `lk-inference` | Built for agents, multimodal capabilities, and fast inference. By Kimi. | *** ## Choosing a Model | Priority | Recommended Model | Model ID | | - | - | - | | **Lowest latency** | Groq GPT OSS 20b | `openai/gpt-oss-20b` | | **Tool calling & high throughput** | Groq GPT OSS 120b | `openai/gpt-oss-120b` | | **Agentic & multimodal** | OpenAI GPT 5.4 Mini | `openai/gpt-5.4-mini` | | **Advanced reasoning** | Google Gemini 4 31b | `google/gemma-4-31b-it` | | **Fast & efficient workflows** | Google Gemini 3.5 Flash Lite | `google/gemini-3.5-flash-lite` | | **Conversational communication** | Google Gemini 3.1 Flash Lite | `google/gemini-3.1-flash-lite` | | **Multimodal & fast inference** | Kimi K2.6 | `moonshotai/kimi-k2.6` | ## What's Next? Connect a self-hosted, fine-tuned, or third-party LLM to your agents. Write system prompts that get the best out of any model. See all STT, LLM, and TTS providers available on TruGen. # Event Callbacks Source: https://docs.trugen.ai/docs/agents/callback Receive real-time webhook events from active conversations to drive your UI, analytics, and business logic. TruGen sends an HTTP `POST` request to your configured `callback_url` whenever something important happens in a conversation: a user starts speaking, the agent is interrupted, a call ends, and more. ## Enabling Webhooks Webhooks are configured at the agent level using two fields: * `callback_url`: your publicly reachable HTTPS endpoint * `callback_events`: the list of event names you want to receive ```bash theme={null} curl --request POST \ --url https://api.trugen.ai/v1/agent/api \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "name": "My Agent", "system_prompt": "You are a helpful assistant", "callback_url": "https://yourdomain.com/webhooks/trugen", "callback_events": [ "agent.interrupted", "agent.started_speaking", "agent.stopped_speaking", "call_ended", "max_call_duration_timeout", "max_call_duration_warning", "participant_left", "tool_call", "utterance_committed", "user.started_speaking", "user.stopped_speaking" ] }' ``` Replace `` with your API key and `callback_url` with your HTTPS endpoint. ## Webhook Request Format Every webhook uses the same base structure: ```json theme={null} { "timestamp": 1764760139.6834729, "conversation_id": "471f0520-cea1-487a-9bcc-37ba37717d81", "type": "pipeline", "event": { "name": "agent.started_speaking", "payload": {} } } ``` | Field | Description | | - | - | | `timestamp` | Unix timestamp (float) when the event was generated | | `conversation_id` | Unique identifier for the conversation session | | `type` | Event source category: always `"pipeline"` for these events | | `event.name` | The specific event type | | `event.payload` | Event-specific data | ## Handling Webhooks ```ts Node.js theme={null} import express from "express"; const app = express(); app.use(express.json()); app.post("/webhooks/trugen", (req, res) => { const { timestamp, conversation_id, type, event } = req.body; switch (event.name) { case "agent.interrupted": // Cut off TTS visual indicators break; case "agent.started_speaking": // Update UI to show agent is speaking break; case "agent.stopped_speaking": // Hide speaking indicators, re-enable user input break; case "call_ended": // Trigger post-call workflows break; case "max_call_duration_timeout": // Show "session ended" message break; case "max_call_duration_warning": // Show "session ending soon" warning break; case "participant_left": // End session or clean up resources break; case "tool_call": // Log tool usage or trigger side effects break; case "utterance_committed": // Store transcript or trigger NLP analysis break; case "user.started_speaking": // Mark user as active break; case "user.stopped_speaking": // Mark turn boundary break; } res.status(200).send("ok"); }); app.listen(3000); ``` ```python Python theme={null} from fastapi import FastAPI, Request from fastapi.responses import JSONResponse app = FastAPI() @app.post("/webhooks/trugen") async def trugen_webhook(request: Request): body = await request.json() event = body.get("event", {}) event_name = event.get("name") payload = event.get("payload", {}) if event_name == "agent.interrupted": print("Agent was interrupted") elif event_name == "agent.started_speaking": print(f"Agent speaking: {payload.get('text')}") elif event_name == "agent.stopped_speaking": print(f"Agent done: {payload.get('text')}") elif event_name == "call_ended": print("Call ended") elif event_name == "max_call_duration_timeout": print(f"Timeout: {payload.get('call_duration')}s") elif event_name == "max_call_duration_warning": print(f"Warning: {payload.get('call_duration')}s of {payload.get('max_call_duration')}s") elif event_name == "participant_left": print(f"Participant left: {payload.get('id')}") elif event_name == "tool_call": print(f"Tool called: {payload.get('tool_name')}") elif event_name == "utterance_committed": print(f"User said: {payload.get('text')}") elif event_name == "user.started_speaking": print("User started speaking") elif event_name == "user.stopped_speaking": print("User stopped speaking") return JSONResponse(content={"status": "ok"}, status_code=200) ``` Keep your webhook handler fast. Acknowledge immediately and offload heavy work to background jobs. ## Event Reference ### `agent.interrupted` Triggered when the user starts speaking before the agent finishes. **Use cases:** cut off TTS visual indicators, log interruptions for conversational analytics. ```json theme={null} { "timestamp": 1764760162.6777198, "conversation_id": "471f0520-cea1-487a-9bcc-37ba37717d81", "type": "pipeline", "event": { "name": "agent.interrupted", "payload": {} } } ``` *** ### `agent.started_speaking` Triggered when the agent starts speaking (TTS + avatar rendering begins). **Use cases:** show a speaking indicator, animate visual elements, log when the agent begins its response. ```json theme={null} { "timestamp": 1764760139.6834729, "conversation_id": "471f0520-cea1-487a-9bcc-37ba37717d81", "type": "pipeline", "event": { "name": "agent.started_speaking", "payload": { "text": "Hi, how are you?" } } } ``` * `payload.text`: the text the agent is about to speak. *** ### `agent.stopped_speaking` Triggered when the agent finishes its current utterance. **Use cases:** hide speaking indicators, re-enable user input, measure speaking duration. ```json theme={null} { "timestamp": 1764760141.1043482, "conversation_id": "471f0520-cea1-487a-9bcc-37ba37717d81", "type": "pipeline", "event": { "name": "agent.stopped_speaking", "payload": { "text": "Hi, how are you?" } } } ``` * `payload.text`: the text that was just spoken. *** ### `call_ended` Triggered when the call with the agent ends cleanly. **Use cases:** trigger post-call workflows (summaries, surveys, CRM updates), log session completion. ```json theme={null} { "timestamp": 1764760201.940625, "conversation_id": "471f0520-cea1-487a-9bcc-37ba37717d81", "type": "pipeline", "event": { "name": "call_ended", "payload": {} } } ``` *** ### `max_call_duration_timeout` Triggered when a conversation reaches its configured maximum duration. **Use cases:** automatically end calls, show a "session ended" UI, enforce usage limits. ```json theme={null} { "timestamp": 1764760631.38699, "conversation_id": "fe2b4550-a87f-440f-a9cd-e5f03208821c", "type": "pipeline", "event": { "name": "max_call_duration_timeout", "payload": { "call_duration": 60.027401447994635, "max_call_duration": 60 } } } ``` * `payload.call_duration`: actual call duration in seconds. * `payload.max_call_duration`: configured maximum duration in seconds. *** ### `max_call_duration_warning` Triggered shortly before a conversation reaches its configured maximum duration: a heads-up before the session is cut off. **Use cases:** show a "session ending soon" warning in your UI, prompt the user to wrap up. ```json theme={null} { "timestamp": 1764760601.123456, "conversation_id": "fe2b4550-a87f-440f-a9cd-e5f03208821c", "type": "pipeline", "event": { "name": "max_call_duration_warning", "payload": { "call_duration": 50.5, "max_call_duration": 60 } } } ``` * `payload.call_duration`: current call duration in seconds. * `payload.max_call_duration`: configured maximum duration in seconds. *** ### `participant_left` Triggered when a participant disconnects from the conversation. **Use cases:** clean up rooms, timers, and state; mark conversation as ended in your backend. ```json theme={null} { "timestamp": 1764760201.940625, "conversation_id": "471f0520-cea1-487a-9bcc-37ba37717d81", "type": "pipeline", "event": { "name": "participant_left", "payload": { "id": "PA_6UYWCLeRkc9t" } } } ``` * `payload.id`: identifier of the participant who left. *** ### `tool_call` Triggered when the agent invokes a tool during a conversation. **Use cases:** log tool usage for analytics, trigger side effects in your backend, audit agent actions. ```json theme={null} { "timestamp": 1764760200.123456, "conversation_id": "471f0520-cea1-487a-9bcc-37ba37717d81", "type": "pipeline", "event": { "name": "tool_call", "payload": { "tool_name": "getOrderStatus", "parameters": { "orderId": "ORD-9821" }, "result": { "status": "shipped", "estimated_delivery": "2026-07-30" } } } } ``` * `payload.tool_name`: the name of the tool that was called. * `payload.parameters`: the inputs passed to the tool by the agent. * `payload.result`: the response returned by the tool. *** ### `utterance_committed` Triggered when the user's utterance has been fully captured and finalised by speech-to-text. **Use cases:** store transcripts, trigger NLP analysis, display final transcript in your UI. ```json theme={null} { "timestamp": 1764760169.0820587, "conversation_id": "471f0520-cea1-487a-9bcc-37ba37717d81", "type": "pipeline", "event": { "name": "utterance_committed", "payload": { "text": "Hello. How are you doing?" } } } ``` * `payload.text`: the final committed text of the utterance. *** ### `user.started_speaking` Triggered when the system detects the user has started speaking. **Use cases:** update UI to show a listening/recording state, trigger analytics on user turn count. ```json theme={null} { "timestamp": 1764760162.4117968, "conversation_id": "471f0520-cea1-487a-9bcc-37ba37717d81", "type": "pipeline", "event": { "name": "user.started_speaking", "payload": {} } } ``` *** ### `user.stopped_speaking` Triggered when the user stops speaking (end of an utterance). **Use cases:** mark turn boundaries for transcription, measure speech duration and turn-taking patterns. ```json theme={null} { "timestamp": 1764760168.8806674, "conversation_id": "471f0520-cea1-487a-9bcc-37ba37717d81", "type": "pipeline", "event": { "name": "user.stopped_speaking", "payload": {} } } ``` *** ## Guardrail Events Are Separate If you've configured [guardrails](/docs/agents/guardrails/overview) on an agent, don't expect their triggers to show up in `callback_events` above: they don't. A guardrail's webhook is configured **per guardrail**, via its own `callback_url` field, not through this agent-level list. When a guardrail fires, TruGen POSTs a `guardrail_triggered` event straight to that URL, with no opt-in required and no relation to whatever you've set in `callback_events`. See [Guardrails → Runtime Behavior](/docs/agents/guardrails/runtime-behavior#the-webhook-event) for the full payload shape and its fire-and-forget delivery caveat. ## Best Practices * **Return 2xx quickly.** Acknowledge in a couple of seconds; offload heavy work to background jobs. * **Be idempotent.** Design your handlers so processing the same event more than once is safe. * **Log by `conversation_id`.** Makes debugging and analytics much easier. * **Use HTTPS.** Your endpoint must be reachable over HTTPS. ## What's Next? Configure `callback_url` and `callback_events` as part of a reusable template. Full agent creation endpoint with all webhook options. # Understanding Teammates Source: https://docs.trugen.ai/docs/agents/conversational-video-agents Real-time conversational video agents that see, hear, and respond with human-like presence. AI Teammates are TruGen's real-time conversational agents: face-to-face, voice-driven, and vision-aware. Unlike a chatbot or voice assistant, an AI Teammate holds a live video conversation, reads the room, and responds the way a person would. This page explains how conversation works under the hood, what you can configure, and how to embed one into your product. Default Call UI ## Conversation Mechanics AI Teammates don't just wait for a user to finish speaking: they actively manage the natural rhythm of conversation. | Mechanic | How It Works | | - | - | | **Speech Recognition** | Runs continuously and incrementally, capturing partial utterances so the agent can begin reasoning before the user finishes speaking | | **Turn Detection** | Detects natural pauses, interruptions, and handovers: the agent knows when to listen, when to speak, and when to yield. Tunable per agent via `turn_handling` (`proactive` / `balanced` / `deliberate`) | | **Backchanneling** | Issues short acknowledgement cues ("mm-hmm", nodding) to signal active listening during user speech | | **Interruption Handling** | Gracefully stops mid-response when the user interjects, rather than talking over them. Sensitivity is tunable via `interruptability` (`low` / `medium` / `high`) | | **Silence Detection** | Monitors for user inactivity and responds with a configurable idle message or ends the session | | **Vision Awareness** | Hawkeye-1 continuously reads gestures, gaze, and body language to feed real-world context into responses | [See the full pipeline →](/docs/agents/pipeline) ## What You Can Configure Each AI Teammate can be fully configured from scratch, or built from a **Template**: a reusable blueprint you can share across multiple agents to keep behaviour consistent. Either way, you control: Define the agent's role, personality, and communication style through a system prompt. Choose voice, accent, and language. AI Teammates support multilingual conversations out of the box. Attach internal docs, FAQs, product data, or APIs so responses are grounded in your content. Connect external APIs and services the agent can call in real time during a conversation. Set custom greeting and farewell messages for session start and end. Set max session length, idle timeout behaviour, and recording preferences. [Learn how to create a template →](/docs/agents/templates) ## Capabilities | Capability | Detail | | - | - | | **Modalities** | Audio, video, text | | **Response Latency** | ≤ 1 second end-to-end | | **Vision** | Gesture, gaze, and body language via Hawkeye-1 | | **Avatar Rendering** | Expressive lip-sync, micro-expressions, and emotional nuance via Huma-2 | | **Languages** | Multilingual: see [supported languages](/docs/agents/multilingual-support) | | **Session Recording** | Optional, configurable per agent | | **Concurrent Sessions** | Unlimited | | **Uptime** | > 99.9% | ## Quick Integration The fastest way to deploy an AI Teammate is a single iframe: no SDK, no WebRTC setup, no media pipeline configuration. For React and Next.js apps, use the React widget instead. Install the package: ```bash theme={null} npm install @aiteammate/agent-widget ``` Import and render the widget: ```tsx theme={null} import "@aiteammate/agent-widget/styles.css"; import { TrugenAgentWidget } from "@aiteammate/agent-widget"; export default function TrugenWidget() { return ( ); } ``` [Full widget guide →](/docs/integrations/widget-integration) Drop the iframe into any frontend (Vue, Angular, Svelte, or plain HTML) and your agent is live instantly. ```html theme={null} ``` [Full integration guide →](/docs/integrations/embed-via-iFrame) ## What's Next? Create and manage reusable persona blueprints for consistent agent behaviour at scale. Explore the full set of APIs to create and manage AI teammates programmatically. # Attach to Agents Source: https://docs.trugen.ai/docs/agents/guardrails/attaching Wire a guardrail to one or many agents via the Studio or the agent API, and know the difference between PUT and PATCH before you use either. A guardrail sits idle until it's attached to an agent. Attach it in the Studio when creating or editing an agent, or via the API by including it in the agent's `guardrail` array, the same pattern used for `tool`, `mcp`, and `knowledge_base`. ## In the Studio Open the agent you want to attach the guardrail to in [app.trugen.ai](https://app.trugen.ai), or start creating a new one. In the agent's configuration tabs, open **Guardrails**. Pick from your workspace's guardrail list. There's no cap. Attach as many as the conversation needs. Save the agent. The change takes effect on the **next** session. See [When updates take effect](#when-updates-take-effect) below. ## Via API Guardrail attachment goes through the same agent endpoints as everything else attached to an agent: ``` PUT /v1/ext/agent/{id} - full replace of attached guardrails PATCH /v1/ext/agent/{id} - additive only (adds without removing existing) ``` Body (either method): ```json theme={null} { "guardrail": [ { "id": "dfbaa3c6-1e90-43df-869a-b023896a198c", "name": "Hate Speech Filter" } ] } ``` An array of `{id, name}`, the same shape as the agent's `tool` and `mcp` keys. Add more objects to attach more guardrails in one call. | Endpoint | Behavior | Use when | | - | - | - | | `PUT /v1/ext/agent/{id}` | Full replace: deletes all existing attachments, then inserts the array you sent | You want to declare the agent's complete guardrail set in one call | | `PATCH /v1/ext/agent/{id}` | Additive only: inserts anything not already attached, never removes | You want to add a guardrail without touching what's already there | ```bash theme={null} curl -X PATCH https://api.trugen.ai/v1/ext/agent/AGENT_ID \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"guardrail": [{"id": "dfbaa3c6-1e90-43df-869a-b023896a198c", "name": "Hate Speech Filter"}]}' ``` Attached guardrails then appear under the `"guardrail"` key in `GET /v1/ext/agent/{id}`, alongside `tool`, `mcp`, and `knowledge_base`. ## Via a template Attach guardrails to a [template](/docs/agents/templates) instead of individual agents when you want every agent built from that template to inherit the same safety checks: ```json theme={null} { "template_name": "Support Template", "template_system_prompt": "You are a friendly support agent.", "guardrail": [ { "id": "dfbaa3c6-1e90-43df-869a-b023896a198c", "name": "Hate Speech Filter" } ] } ``` Any agent later created from this template automatically has the guardrail attached. ## Detaching a guardrail There's no partial-remove endpoint. `PATCH` is insert-only: it cannot detach anything. The only way to remove a single guardrail from an agent is `PUT` with the full `guardrail` array **minus** the entry you want gone, since `PUT` deletes and reinserts the whole list. If you only have the guardrail's `id` you want to remove, fetch the agent first (`GET /v1/ext/agent/{id}`), drop that entry from the returned `guardrail` array, then `PUT` the rest back. ## When updates take effect Guardrails are fetched and embedded into an agent's dispatch config **exactly once**, at the moment a new conversation is created. They're never re-fetched mid-call. Any attach, detach, or edit you make after a call has already started has **zero effect on that running call**. It only applies to the next session. If you need a change to apply immediately, end the active session explicitly with [`DELETE /v1/conversation/{conversationId}`](/api-reference/endpoint/conversationdelete) after your update lands. ## What's Next? What happens the moment a guardrail fires, and the webhook payload it sends. Field reference and how to write a prompt the LLM will act on. # Creating a Guardrail Source: https://docs.trugen.ai/docs/agents/guardrails/creating Field reference, validation rules, and how to write a guardrail prompt the LLM will actually act on. Guardrails are created once per workspace and reused across as many agents as you like. Creating one is a separate step from [attaching it](/docs/agents/guardrails/attaching). ## Endpoint ```bash theme={null} POST https://api.trugen.ai/v1/ext/guardrail Header: x-api-key: Content-Type: application/json ``` ## Fields | Field | Type | Required | Description | | - | - | - | - | | `name` | string | Yes | Human-readable label. Also used to derive the permanent `key` (see below). `400` if missing or empty. | | `category` | string | No | Free-text tag, no fixed list. See [example categories](/docs/agents/guardrails/overview#example-categories). Can be an empty string. | | `prompt` | string | Yes | The rule text: describes what user behavior should trigger this guardrail. This is what the LLM evaluates the conversation against. `400` if missing or empty. | | `response_message` | string | No | Spoken to the user verbatim when the guardrail fires. If empty, the guardrail falls back to a moderation-endpoint check instead. See [Runtime Behavior](/docs/agents/guardrails/runtime-behavior). | | `callback_url` | string (URL) | No | Where a `guardrail_triggered` event is POSTed when this guardrail fires. Must be a well-formed `http(s)://` URL if present (`400` if malformed). Omit it and nothing is ever posted for this guardrail. | There are no length limits on `name`, `category`, `prompt`, or `response_message`; all stored as unbounded text. ## Example ```bash theme={null} curl -X POST https://api.trugen.ai/v1/ext/guardrail \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Hate Speech Filter", "category": "Content Safety", "prompt": "Trigger when the user uses hateful, discriminatory, or abusive language toward a person or group.", "response_message": "I'\''m sorry, but I can'\''t help with that. Let'\''s keep things respectful.", "callback_url": "https://yourapp.com/webhooks/guardrail" }' ``` Response (`201 Created`): ```json theme={null} { "id": "dfbaa3c6-1e90-43df-869a-b023896a198c", "message": "Guardrail created" } ``` **The `key`.** The server derives a URL/LLM-safe slug from `name` at creation time: lowercased, spaces and punctuation replaced with underscores (e.g. `"Hate Speech Filter"` becomes `hate_speech_filter`). If that slug collides with one already in your workspace, a numeric suffix is appended (`hate_speech_filter_2`). This `key` is permanent: renaming the guardrail later via `PUT` never changes it, and it's the identifier the running agent uses as the tool name. ## Validation rules | Condition | Status | Body | | - | - | - | | `name` missing or empty | `400` | `{"error": "name is required"}` | | `prompt` missing or empty | `400` | `{"error": "prompt is required"}` | | `callback_url` present but not a valid `http(s)://` URL | `400` | `{"error": "callback_url must be a valid http(s) URL"}` | | `category` or `response_message` is an empty string | N/A | Allowed, not an error | | `PUT`/`DELETE` on an unknown or foreign `id` | `404` | `{"message": "Guardrail not found"}` | ## Listing guardrails ```bash theme={null} curl https://api.trugen.ai/v1/ext/guardrail -H "x-api-key: YOUR_API_KEY" ``` Response (`200 OK`), a plain array (not wrapped in a `data` key), scoped to your workspace only. `category`, `response_message`, and `callback_url` come back as `""`, never `null`, when unset: ```json theme={null} [ { "id": "dfbaa3c6-1e90-43df-869a-b023896a198c", "key": "hate_speech_filter", "name": "Hate Speech Filter", "category": "Content Safety", "prompt": "Trigger when the user uses hateful, discriminatory, or abusive language toward a person or group.", "response_message": "I'm sorry, but I can't help with that. Let's keep things respectful.", "callback_url": "https://yourapp.com/webhooks/guardrail", "created_at": "2026-08-14T11:38:46.479224Z", "updated_at": "2026-08-14T11:38:46.479224Z" } ] ``` There's no `GET /ext/guardrail/{id}`. List-all is the only read endpoint today. ## Updating a guardrail `PUT /ext/guardrail/{id}` is a **full replace** of every client-settable field, not a partial patch. Send the complete body, not just the field you're changing. ```bash theme={null} curl -X PUT https://api.trugen.ai/v1/ext/guardrail/dfbaa3c6-1e90-43df-869a-b023896a198c \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Hate Speech Filter", "category": "Content Safety", "prompt": "Updated prompt text.", "response_message": "Let'\''s keep things respectful.", "callback_url": "" }' ``` Response (`200 OK`): `{ "id": "dfbaa3c6-1e90-43df-869a-b023896a198c", "message": "Guardrail updated" }` `key` is never changed by an update, even if `name` changes. ## Deleting a guardrail ```bash theme={null} curl -X DELETE https://api.trugen.ai/v1/ext/guardrail/dfbaa3c6-1e90-43df-869a-b023896a198c \ -H "x-api-key: YOUR_API_KEY" ``` Response (`200 OK`): `{ "id": "dfbaa3c6-1e90-43df-869a-b023896a198c", "message": "Guardrail deleted" }` Deleting a guardrail **does not cascade** to the agents it's attached to. The attachment reference is left dangling. It's harmless at runtime (silently excluded from dispatch), but the dangling row persists indefinitely with no automatic cleanup. If you care about a clean state, [detach it](/docs/agents/guardrails/attaching#detaching-a-guardrail) from every agent first. ## Writing an effective guardrail prompt `prompt` is the only signal the LLM has for deciding whether to call this guardrail. Vague prompts get missed or over-triggered. Use the pattern: > **\[who]** **\[is doing what]** **\[under what condition]** **Too vague:** ``` Trigger for anything inappropriate. ``` **Specific enough:** ``` Trigger when the user uses hateful, discriminatory, or abusive language toward a person or group, including slurs, dehumanizing language, or explicit calls for violence based on a protected characteristic. ``` ``` Trigger when the user shares or asks the agent to repeat a full credit card number, social security number, or government ID number in the conversation. ``` A guardrail's `prompt` competes with every other tool and instruction the LLM is weighing on a given turn. Specificity is what makes it win that competition reliably. It also has to be reachable in the first place: see [Reliability depends on your prompt](/docs/agents/guardrails/overview#how-it-works) for why the system prompt still needs to tell the agent to use its guardrails at all. ## What's Next? Wire this guardrail to one or many agents. What happens the moment a guardrail fires. # Guardrails Source: https://docs.trugen.ai/docs/agents/guardrails/overview Safety-check rules your agent can call mid-conversation: a canned response, a moderation check, and an optional webhook when something needs a second look. A **guardrail** is a safety-check rule attached to an agent. During a live conversation, the agent's LLM can invoke a guardrail as a tool when it decides a user's message might need checking: hate speech, PII, misinformation, anything you describe. When a guardrail fires, the agent either speaks a canned response or falls back to a moderation check, and, if you've configured one, POSTs an event to a webhook URL you provide. Guardrails are global to your workspace and reusable across agents. Creating one doesn't do anything on its own: it has to be [attached to an agent](/docs/agents/guardrails/attaching) before it's live in any conversation. ## How it works Define a `name`, a `prompt` describing what should trigger it, and a `response_message`. See [Creating a Guardrail](/docs/agents/guardrails/creating). One guardrail can be attached to many agents. See [Attach to Agents](/docs/agents/guardrails/attaching). On each turn, the agent's LLM weighs the user's message against every attached guardrail's `prompt` and decides whether one applies, exactly like any other [tool](/docs/agents/tools/overview). The agent speaks the configured `response_message` and the turn ends immediately. If a `callback_url` is set, a `guardrail_triggered` event is POSTed to it. See [Runtime Behavior](/docs/agents/guardrails/runtime-behavior). A guardrail only fires if the LLM decides to call it. There's no code-level enforcement forcing the check. Reliability depends heavily on your system prompt explicitly telling the agent to use its guardrails. See [Prompting Strategies](/docs/agents/prompting-strategies#5-guardrails). ## Example categories `category` is a free-text field with no fixed list. Use whatever taxonomy makes sense for your workspace. A few common ones to start from: | Category | Example use | | - | - | | **Content Safety** | Hate speech, harassment, abusive language | | **PII & Privacy** | Requests to share SSNs, card numbers, medical records | | **Misinformation** | Claims the agent shouldn't confirm or deny | | **Compliance** | Regulated advice: medical, legal, financial | | **Brand Safety** | Off-topic, competitor mentions, politically sensitive topics | ## Verifying a guardrail There's no test sandbox for guardrails yet. Attach it to an agent and talk to it directly: 1. [Attach](/docs/agents/guardrails/attaching) the guardrail to a test agent. 2. Start a session and send a message designed to trigger it. 3. Confirm the agent responds with your exact `response_message`. 4. If you set a `callback_url`, confirm the `guardrail_triggered` event arrived. See [Runtime Behavior](/docs/agents/guardrails/runtime-behavior#the-webhook-event). If the agent doesn't trigger it, the most common cause is the system prompt never mentioning that guardrails should be checked. See the reliability note above before assuming the guardrail itself is misconfigured. ## Known limitations * **No single-item fetch.** Only `POST` (create), `GET` (list all), `PUT` (update), and `DELETE` exist. There's no `GET /ext/guardrail/{id}`. * **No partial detach.** Removing one guardrail from an agent means `PUT`-ing the full attached list minus that entry. See [Attaching](/docs/agents/guardrails/attaching#detaching-a-guardrail). * **No test/sandbox affordance.** Verify by attaching and talking to the agent. ## What's Next? Field reference, validation rules, and how to write an effective guardrail prompt. Wire a guardrail to one or many agents via the Studio, the API, or PATCH vs PUT. What actually happens when a guardrail fires, and the `guardrail_triggered` webhook payload. Make sure your system prompt actually tells the agent to check its guardrails. # Runtime Behavior Source: https://docs.trugen.ai/docs/agents/guardrails/runtime-behavior What actually happens when a guardrail fires during a live call: the three outcomes, the webhook payload, and the caveats worth knowing before you rely on either. This page covers what happens **after** a guardrail is [created](/docs/agents/guardrails/creating) and [attached](/docs/agents/guardrails/attaching): the moment-by-moment behavior during a live conversation. ## How a guardrail becomes available When a conversation starts, the backend fetches every **active** guardrail attached to that agent and embeds it into the agent's dispatch config: ```json theme={null} { "actions": { "guardrails": [ { "name": "hate_speech_filter", "description": "Trigger when the user uses hateful, discriminatory, or abusive language toward a person or group.", "category": "Content Safety", "event_messages": { "on_trigger": { "message": "Let's keep things respectful." } }, "callback_url": "https://yourapp.com/webhooks/guardrail" } ] } } ``` `event_messages` only appears if `response_message` was set on the guardrail; `callback_url` only appears if one was configured. This happens **once**, at conversation creation. See [When updates take effect](/docs/agents/guardrails/attaching#when-updates-take-effect). From there, the LLM decides, turn by turn and based on the guardrail's `prompt`/`description`, whether a given user message warrants calling it. Nothing in the platform forces this check; it's LLM judgment, same as any other [tool](/docs/agents/tools/overview). ## The three outcomes A triggered guardrail is never silent. The user always hears something. Which of these three happens depends entirely on how the guardrail is configured, not on anything the LLM decides: | # | Path | Condition | What the user hears | | - | - | - | - | | 1 | **Canned response** | `response_message` is set | The agent speaks that exact line, then the turn ends immediately. Deterministic, with no LLM improvisation added on top. | | 2 | **Moderation check** | `response_message` is empty *and* a moderation backend is configured | The check result is handed to the LLM as the tool's result, and the LLM writes its own reply based on it. | | 3 | **Error fallback** | The moderation check can't run, or fails | The LLM receives a tool error and reacts however its prompting leads it to: typically an apology or a generic response. Not scripted, not guaranteed. | ## The `verdict` field If the moderation path fires (path 2), `verdict` has **no fixed schema**. It's a raw pass-through of whatever the moderation endpoint returns: * Valid JSON response → parsed and passed through as-is. * Non-JSON response → wrapped as `{"raw": ""}`. * The check itself fails → an error dict instead, such as `{"error": "check request failed"}` or `{"error": ""}`. Nothing in the platform inspects `verdict`'s contents. There's no automatic "if flagged, block" logic anywhere in the pipeline. It's handed to the LLM as a tool result, and whether the agent refuses, warns, or continues normally is entirely up to the LLM's own judgment and your system prompt, not something TruGen enforces for you. ## The webhook event This is a **separate mechanism** from the agent-level `callback_url` / `callback_events` system documented in [Event Callbacks](/docs/agents/callback). That system is an opt-in list of pipeline events (`call_ended`, `tool_call`, etc.) configured once per agent. A guardrail's `callback_url` is configured **per guardrail**, is not part of `callback_events`, and fires automatically, with no opt-in list, any time that specific guardrail triggers. If a guardrail has `callback_url` set, a `guardrail_triggered` event is POSTed there every time it fires, regardless of which of the three outcomes above occurred: ```json theme={null} { "event": "guardrail_triggered", "guardrail": { "name": "hate_speech_filter", "category": "Content Safety" }, "content": "the exact text that was checked", "response_message": "Let's keep things respectful.", "verdict": null, "conversation_id": "4cd87bec-d8f2-4b56-804b-bc3dcef0ee7e", "speech_id": "speech_eea2b17d1c65", "agent_id": "Clara", "timestamp": "2026-08-14T11:38:46.479224Z" } ``` | Field | Description | | - | - | | `event` | Always `"guardrail_triggered"`. | | `guardrail.name` | The guardrail's `key` (not the display `name`). | | `guardrail.category` | The `category` set at creation. | | `content` | The exact user text that was checked. | | `response_message` | The canned message spoken, if path 1 fired. `null`/absent otherwise. | | `verdict` | `null` unless the moderation path (path 2) fired (see above for its shape). | | `conversation_id` | The session this happened in. | | `speech_id` | Identifier for the specific turn. | | `agent_id` | **The agent's display name, not its UUID.** Despite the key name, sourced directly from the agent's `name` field. | | `timestamp` | When the guardrail fired. | Delivery is **fire-and-forget**: no retries, and failures are swallowed silently. If `callback_url` isn't set on a guardrail, nothing gets posted anywhere for it: not to this endpoint, not anywhere else. That's expected behavior, not a bug. Don't build logic that assumes guaranteed delivery; treat this as a best-effort notification, not an audit log. ## What's Next? The separate, agent-level webhook system this is easy to confuse with. Wire a guardrail to an agent, and know when changes take effect. # Attach to Agents Source: https://docs.trugen.ai/docs/agents/knowledge/attaching Wire your Knowledge Base to one or many agents: via the Studio, via the agent API, or through a template. A Knowledge Base sits idle until it's attached to an agent. Attach it in the Studio when creating or editing an agent, or via the API by including the KB's ID in the agent's `knowledge_base` array. ## In the Studio Open the agent you want to attach the KB to in [app.trugen.ai](https://app.trugen.ai). In the agent's configuration tabs, open **Knowledge Base**. Pick from your list of KBs. You can attach multiple: the agent decides which one to search for each user question. Save the agent. The next session picks up the new KB configuration automatically. ## Via API Include one or more KB references in the agent's `knowledge_base` array when creating or updating an agent: ```json theme={null} { "agent_name": "Support Agent", "agent_system_prompt": "You help customers with product questions.", "knowledge_base": [ { "id": "kb_prod_docs_123", "name": "Product-Docs" }, { "id": "kb_faqs_456", "name": "Support-FAQs" } ] } ``` You can attach as many KBs as needed. Each KB's Name and Description tell the agent when to search that specific one: see [Naming and describing well](/docs/agents/knowledge/creating#naming-and-describing-well). Full endpoint reference: [Create Agent](/api-reference/endpoint/agentcreate) and [Update Agent](/api-reference/endpoint/agentupdate). ## Via a template Attach Knowledge Bases to a [template](/docs/agents/templates) instead of individual agents when you want every agent built from that template to inherit the same knowledge: ```json theme={null} { "template_name": "Support Template", "template_system_prompt": "You are a friendly support agent.", "knowledge_base": [ { "id": "kb_prod_docs_123", "name": "Product-Docs" }, { "id": "kb_faqs_456", "name": "Support-FAQs" } ] } ``` Any agent later created from this template automatically has both KBs attached. ## Multi-KB strategy Attaching multiple focused Knowledge Bases to one agent almost always beats attaching a single mixed one. The LLM uses each KB's Name and Description to pick the right one: well-scoped KBs give it a strong signal. **Recommended:** ``` Support Agent ├── Product-Docs ├── Pricing-2026 ├── Support-FAQs └── Return-Policies ``` Each KB has \~10–30 focused documents. The agent picks the right KB for each user question before searching inside it. **Not recommended:** ``` Support Agent └── All-Company-Docs (300 mixed documents) ``` Retrieval quality drops sharply as unrelated content piles up. The LLM has no meaningful signal to prefer one region of the KB over another. ## When updates take effect Adding or removing a Knowledge Base on an agent takes effect on the **next session**: active conversations keep the previous configuration until they end. If you need to force the change on running sessions, end them explicitly with [`DELETE /v1/conversation/{conversationId}`](/api-reference/endpoint/conversationdelete) after saving the agent update. ## Verifying retrieval The best way to verify a KB is working is to talk to the agent. Ask a question whose answer you know is inside the KB: * If the agent answers correctly → retrieval is working. * If the agent hedges or gives generic info → the KB may not have been picked. Check the KB's Name and Description are specific enough. See [Naming and describing well](/docs/agents/knowledge/creating#naming-and-describing-well). * If the agent hallucinates → the answer isn't in the KB, or retrieval isn't finding the right chunk. Rephrase the source content, or split the doc. ## Next steps Attach a KB to a template so every agent built from it inherits the knowledge. Add more content to a KB after attaching. # Setup Source: https://docs.trugen.ai/docs/agents/knowledge/creating Create a Knowledge Base in the Studio or via the API: and name it so the agent can find it. Every Knowledge Base starts with a **name** and a **description**. Both fields matter more than most people expect: the agent reads them to decide *whether* to search this KB for a given user question. A vague name or an empty description means the LLM never picks the KB, no matter how good the content is. ## In the Studio Go to [app.trugen.ai](https://app.trugen.ai) and click **Knowledge Base** in the left panel under **Configure**. Click **Create New**. Give it a clear **Name** and a specific **Description**. You can add content at creation time or later. See [Adding Content](/docs/agents/knowledge/uploading) for supported formats. Click **Save & Create**. Content is queued for indexing. Once processing completes, the KB is ready to attach to agents. ## Via API Create a Knowledge Base with a name and description: ```bash theme={null} curl --location 'https://api.trugen.ai/v1/ext/kb' \ --header 'x-api-key: YOUR_API_KEY' \ --form 'name="HR-Policies"' \ --form 'description="Use this whenever the user asks about HR policies, leave entitlements, benefits, or employee guidelines."' \ --form 'is_active="true"' ``` The response returns a Knowledge Base `id`: save it. You'll use it to add documents and attach the KB to agents. ```json theme={null} { "id": "kb_abc123", "message": "Knowledge base created successfully" } ``` Requests use `multipart/form-data` (not JSON) because the same endpoint accepts optional file uploads at creation time. Total request size is capped at **100 MB**. Full endpoint reference: [Create Knowledge Base](/api-reference/endpoint/knowledgebasecreate). ## Naming and describing well The Name and Description drive retrieval routing. Write them the way you'd write a prompt for a colleague deciding which folder to open. ### Good ``` Name: HR-Policies Description: Use this whenever the user asks about HR policies, leave entitlements, benefits, or employee guidelines. ``` ``` Name: Product-Docs Description: Use this when the user asks about product features, setup instructions, integrations, or technical specifications. ``` ``` Name: Pricing-2026 Description: Use this for questions about plan pricing, seat costs, discounts, and Enterprise custom quotes. ``` ### Bad ``` Name: KB1 Description: Company info ``` Both are too vague. The LLM has no signal to pick this KB over another. ## Organization strategy You'll almost always get better results with **multiple focused Knowledge Bases** than one large mixed one. | Approach | When it works | When it doesn't | | - | - | - | | **One KB per domain** (recommended) | Users ask questions clearly rooted in one topic. Each KB has \~5–50 focused documents. | : | | **One giant KB with all content** | You have very little content and it's all closely related. | Retrieval quality drops sharply once mixed content exceeds \~50 documents. | Practical splits that work well: * **Product-Docs + Pricing + Support-FAQs** (SaaS) * **HR-Policies + IT-Support + Facilities** (internal ops) * **API-Reference + Getting-Started + Troubleshooting** (developer tools) ## Managing your Knowledge Bases * **List all KBs**: `GET /v1/ext/kbs` * **Get a specific KB**: `GET /v1/ext/kb/{kbId}` (returns metadata plus attached documents) * **Update name/description**: `PUT /v1/ext/kb/{kbId}` * **Delete a KB**: `DELETE /v1/ext/kb/{kbId}` See the full [Knowledge Base API Reference](/api-reference/endpoint/knowledgebasecreate). ## Next steps Upload documents, add plain text, or scrape URLs. Wire your KB to one or many agents. # Knowledge Base Source: https://docs.trugen.ai/docs/agents/knowledge/overview Give your agents access to your documents, FAQs, and web content: grounded answers via Retrieval-Augmented Generation. A **Knowledge Base** is a collection of your content (documents, plain text, and websites) that your agents search when answering questions. Instead of relying on generic LLM knowledge, agents retrieve from your Knowledge Base and answer with information that's accurate, brand-aligned, and up to date. Knowledge Bases are **reusable**. Multiple agents and templates can attach to the same one, so you keep information consistent across all your agents from one place. ## How retrieval works TruGen supports two retrieval modes that control **when** and **how** the agent queries your Knowledge Base. | Mode | How it works | | - | - | | **Agentic RAG** | The LLM decides when and which Knowledge Base to search based on the user's query and conversation context. More precise: only retrieves when relevant. | | **Traditional RAG** | Every user query is searched against all configured Knowledge Bases, and the retrieved context is always passed to the LLM. Simpler and more predictable. | For most use cases, **Agentic RAG** produces better results: the agent retrieves only when it's genuinely needed, which reduces noise and improves response quality. ## Supported content types Upload **PDF**, **DOCX**, **PPTX**, etc. files. Content is extracted, chunked, and indexed automatically. Best for policies, manuals, product documentation, and structured reports. Paste raw text directly. Best for FAQs, scripted responses, quick reference content, or anything you want to control precisely without a file upload. Provide a URL to scrape a single page, or crawl an entire site. Best for public documentation, help centres, and product pages. Full format and size limits: see [Adding Content](/docs/agents/knowledge/uploading). ## The three-step lifecycle Every Knowledge Base moves through three phases: Set the name, description, and (optionally) initial content. See [Creating a Knowledge Base](/docs/agents/knowledge/creating). Upload documents, paste text, or point at URLs. TruGen extracts, cleans, chunks, and indexes each piece automatically. See [Adding Content](/docs/agents/knowledge/uploading). Reference the Knowledge Base by ID from one or more agents (or a template). Agents pick up changes on the next session. See [Attaching to Agents](/docs/agents/knowledge/attaching). ## Next steps Create your first KB in the Studio or via the API. Supported formats, size limits, and how content is processed. # Upload Content Source: https://docs.trugen.ai/docs/agents/knowledge/uploading Upload PDFs and DOCX files, paste plain text, or point at URLs: TruGen extracts, chunks, and indexes everything automatically. Once a Knowledge Base exists, you fill it with content. TruGen accepts three kinds of source material and handles all the extraction, cleaning, chunking, and indexing under the hood. ## Content types | Type | Formats | Where to add | | - | - | - | | **File upload** | `.pdf`, `.docx`, `.doc`, `.txt`, `.pptx`, `.png`, `.jpg`, `.jpeg`, `.md`, `.json` | Studio or API | | **Plain text** | Raw text (any length) | Studio | | **URL** | Single page or full-site crawl | Studio | ## Size limits | Scope | Limit | | - | - | | Single document upload (`POST /v1/ext/kb/{kbId}/doc`) | **10 MB** per file | | Bulk KB creation with attached files (`POST /v1/ext/kb`) | **100 MB** total request size | Files above these limits are rejected with a 400 error. For larger source material, split into smaller documents before uploading: smaller focused docs also retrieve better than one big file. ## Uploading a file via API Upload a single document to an existing Knowledge Base using its `kbId`: ```bash theme={null} curl --request POST \ --url https://api.trugen.ai/v1/ext/kb/{kbId}/doc \ --header 'x-api-key: YOUR_API_KEY' \ --form 'file=@/path/to/document.pdf' ``` Response includes the created document's ID: ```json theme={null} { "doc_id": "doc_abc123", "message": "Document added successfully" } ``` Full endpoint reference: [Add Documents to Knowledge Base](/api-reference/endpoint/knowledgebaseadddoc). ## Adding plain text Plain text lives inline in the KB: no file is created. Best for FAQs, scripted responses, or short reference content you want to control word-for-word. Add plain text in the Studio's Knowledge Base editor. Prefer plain text when the content is short and you want precise wording. Prefer file uploads when the content is long, already lives in a document, or needs to survive versioning outside TruGen. ## Adding a URL or website Point the Studio's URL input at a webpage and TruGen fetches, cleans, and indexes it. You can either: * **Add a single URL**: fetches and indexes just that page * **Crawl a root URL**: walks the site and indexes every reachable page under that root Best for public documentation, help centres, changelogs, and product pages. URL and crawl support is currently a Studio feature. If you need to add URLs programmatically at scale, contact [support@trugen.ai](mailto:support@trugen.ai). ## How content is processed Every piece of content passes through the same pipeline: Text is pulled from the file, page, or plain-text input. Layout, images, and formatting are stripped down to the underlying content. Boilerplate (nav, footers, page numbers) and low-signal noise are removed. The document is split into semantically coherent chunks sized for embedding retrieval. Each chunk is embedded and stored in the vector index. Once indexed, the content is searchable by any agent the KB is attached to. Processing is asynchronous. For large PDFs or full-site crawls, indexing may take a minute or two. During that window, the document exists in the KB but isn't yet retrievable: attached agents keep answering from the rest of the KB's indexed content. ## Removing a document Delete a specific document from a KB by its `docId`: ```bash theme={null} curl --request DELETE \ --url https://api.trugen.ai/v1/ext/kb/doc/{docId} \ --header 'x-api-key: YOUR_API_KEY' ``` The document is removed from the index immediately. Attached agents stop retrieving from it on the next session. ## Best practices * **Clean text beats fancy PDFs.** PDFs with unusual layouts, multi-column pages, or footnotes retrieve poorly. Convert to Markdown or a clean PDF export when you can. * **Split large documents.** A 100-page master PDF retrieves worse than 10 well-scoped 10-page documents. * **Use descriptive filenames.** `hr-leave-policy-2026.pdf` beats `document-final-v2.pdf`. Filenames show up in retrieval reasoning. * **Re-upload changed docs rather than editing.** Delete the old version, upload the new one. Cleaner than trying to overwrite in place. ## Next steps Wire your Knowledge Base to one or many agents. Back to the setup guide. # External Meetings Source: https://docs.trugen.ai/docs/agents/meetings/overview Give your AI Teammate its own meeting email and invite it into any live video call: just like a person. External Meetings lets your AI Teammate join live video calls on Google Meet, Zoom, Microsoft Teams, or Webex: as a real participant. You invite it the same way you'd invite any colleague: by adding its email to the meeting. It shows up on time, listens, responds, and stores a full transcript when the call ends. No bots to configure. No platform integrations to set up. Just an email address. ## Enabling External Meetings When creating or editing an agent in the [Studio](https://app.trugen.ai), open the **Advanced** section and toggle **Join external meetings** on. Once enabled, you're prompted to pick a prefix and your agent is assigned a **dedicated meeting email address** on the `@agent.trugen.ai` domain: for example `alex@agent.trugen.ai`. The Studio checks availability as you type so you can claim a prefix that matches the agent's persona. The email address is unique to each agent: the platform reserves your chosen prefix. Different teammates get different emails, so you can invite specific agents to specific meetings. ## Inviting Your Teammate to a Meeting Once your agent has a meeting email, inviting it is exactly like inviting a person: Find the `@agent.trugen.ai` email address in the agent's **Advanced** settings in the Studio. When scheduling a meeting on Google Calendar, Outlook, or any other calendar tool, add the agent's email as a guest: just as you would with a colleague. At the scheduled start time, your AI Teammate joins the call under its display name. No manual action required. The agent listens in real time, processes the conversation, and responds based on its configuration, persona, and knowledge base. When the call ends, the full transcript and recording are stored automatically: available for review or downstream workflows. ## Supported Platforms The agent handles platform-specific join flows automatically: including waiting rooms, lobby screens, and recording permission dialogs. ## What the Agent Does in a Meeting | Capability | Description | | - | - | | **Real-Time Listening** | Transcribes speech as it happens, tracking who said what | | **Live Responses** | Speaks and responds naturally during the conversation | | **Participant Awareness** | Knows who's in the call and can address participants by name | | **Recurring Meetings** | Joins every occurrence of a recurring series; handles cancellations and reschedules automatically | | **Vision Understanding** | With Vision enabled, analyses the live video feed for emotions, gaze, attention, and more | | **Tool Use** | Can call APIs, trigger workflows, or look up knowledge base content mid-call | ## Multi-Participant Calls TruGen agents are built for real meetings: not just one-on-one conversations. They participate naturally in calls with multiple people, following the flow of the discussion without interrupting or speaking out of turn. This is powered by our proprietary **Chime In** model, which continuously tracks the conversation and determines the right moment for the agent to contribute. It understands turn-taking dynamics, detects when a question is directed at the agent, and stays silent when the conversation is between other participants: just like a human attendee would. The result is an agent that feels like a real meeting participant, not a bot waiting to be explicitly triggered. ## Common Use Cases * **AI interviewer**: joins hiring calls, asks structured questions, and captures candidate responses * **Sales agent**: attends discovery calls to answer product questions and qualify leads live * **Onboarding assistant**: guides new hires through their first meetings interactively * **Compliance monitor**: attends regulated calls and flags policy violations in real time * **Meeting summariser**: listens, captures key points, and sends follow-ups automatically ## What's Next? Enable real-time video analysis during live meetings. Connect your content so the agent answers accurately in any meeting context. Extend the agent with API calls, integrations, and automation during calls. Receive real-time webhook events from active meeting sessions. # Agent Memory Source: https://docs.trugen.ai/docs/agents/memory Persist important user details across conversations so your agent remembers who it's talking to. Memory allows AI Teammates to save key details from one conversation and recall them in the next. Combined with **Custom Instructions**, you control exactly what gets remembered and how much detail is retained. ## Getting Started Go to [app.trugen.ai](https://app.trugen.ai). Click **Create New Agent** or open an existing one. Open the **Memory** tab and enable the **Custom Instruction** toggle. Write an instruction specifying what details the agent should save. Talk to the agent. It will save memory entries based on your instruction and recall them in future conversations with the same user. ## How Memory Works When a conversation starts, the agent loads the user's previous chat history and selects the most relevant context to bring into the current session. As the conversation progresses, new details are stored: making them available the next time that user returns. Review your privacy settings and ensure user consent is in place before storing sensitive personal details. ## Custom Instruction Examples Custom Instructions tell the agent what categories of information to capture. Below are two ready-to-use examples. ### Sales Agent ``` 1. Personal Profile - Capture full name, preferred name, date of birth or age, relationship status, family members and pets. - Record context and source ("User mentioned on 2024-05-10") and update whenever changes occur. 2. Life Events & Memories - Log notable experiences (vacations, celebrations, milestones) with date, location, participants, and significance. - Tag memories by theme (e.g., travel, accomplishment) and mark emotional valence (positive/negative/neutral). 3. Emotional & Mental Wellbeing - Track expressed moods, feelings, stressors, and sources of joy or concern. - Note changes over time to identify patterns. 4. Preferences & Interests - Store likes/dislikes across food, music, movies, hobbies, travel, and routines. - Include specificity (e.g., "Prefers jazz over classical", "Loves Thai cuisine: especially pad Thai"). 5. Goals, Plans & Tasks - Record short- and long-term objectives, project steps, resolutions, and scheduled events with deadlines. - Track progress updates and flag overdue tasks. 6. Social Network & Communication - Note close friends, mentors, and colleagues with their relationship context and preferred contact methods. 7. Feedback & Reflections - Store evaluations of recent experiences, lessons learned, and aspirations for growth. 8. Health & Wellness Routines - Log exercise habits, dietary preferences, sleep patterns, and relaxation practices in a personal (non-clinical) context. Implementation Guidelines: - Timestamp every entry and note the context in which information was shared. - Update or archive entries as details evolve; avoid duplication by merging overlapping data. - Enable retrieval by keyword, category, date range, and emotional tag. ``` ### Educational Mentor ``` Types of Information to Remember: 1. Personal & Academic Profile - User's name, institution, grade or year, major, enrolled courses. 2. Academic Goals & Aspirations - Target GPA, study-abroad plans, scholarship or internship applications, career objectives. 3. Assignments, Exams & Deadlines - Upcoming homework, projects, tests, exam dates, and study schedules. 4. Learning Preferences & Styles - Preferred media (visual, auditory, kinesthetic), class format, study environment, group vs. solo learning. 5. Extracurricular & Research Activities - Clubs, sports, competitions, volunteer work, and research projects. 6. Challenges & Support Needs - Difficult subjects, requests for tutoring or accommodations, time-management issues. 7. Achievements & Progress - Awards, certifications, completed courses, skills acquired, milestones reached. 8. Feedback & Motivation Factors - Opinions on classes or instructors, preferred teaching materials, motivational triggers or obstacles. Memory Depth Guidance: Retain detailed context for the most recent three interactions; summarise older details as needed to preserve relevance and continuity. ``` ## What's Next? Define the full persona and behaviour blueprint for your agent. Give your agent access to documents, FAQs, and data sources. # Multilingual Support Source: https://docs.trugen.ai/docs/agents/multilingual-support Configure speech-to-text and text-to-speech across 60+ languages, with automatic language detection and dialect support. TruGen supports conversations in 60+ languages. The speech pipeline uses **Deepgram**, **AssemblyAI**, and **Speechmatics** for transcription (STT) and **ElevenLabs**, **Cartesia**, **Rime**, **Fish Audio**, and **Inworld TTS** for voice synthesis (TTS): all of which auto-adapt when you use `multi` mode. ## Quick start For agents that need broad language coverage without picking a specific language, use `multi`: ```json theme={null} "stt": { "language": "multi" } ``` The STT engine auto-detects the spoken language, and TTS renders in the same language. Works for the most common cross-language flows. For a specific language, use its code (see tables below): ```json theme={null} "stt": { "language": "en-IN" } ``` ## Supported languages ### European | Language | Code | Dialect variants | | - | - | - | | **Bulgarian** | `bg` | : | | **Catalan** | `ca` | : | | **Czech** | `cs` | : | | **Danish** | `da` | `da-DK` | | **Dutch** | `nl` | `nl-BE` (Flemish) | | **English** | `en` | `en-US`, `en-GB`, `en-AU`, `en-NZ`, `en-IN` | | **Estonian** | `et` | : | | **Finnish** | `fi` | : | | **French** | `fr` | `fr-CA` (Canada) | | **German** | `de` | `de-CH` (Switzerland) | | **Greek** | `el` | : | | **Hungarian** | `hu` | : | | **Italian** | `it` | : | | **Latvian** | `lv` | : | | **Lithuanian** | `lt` | : | | **Norwegian** | `no` | : | | **Polish** | `pl` | : | | **Portuguese** | `pt` | `pt-BR`, `pt-PT` | | **Romanian** | `ro` | : | | **Russian** | `ru` | : | | **Slovak** | `sk` | : | | **Spanish** | `es` | `es-419` (Latin America) | | **Swedish** | `sv` | `sv-SE` | | **Turkish** | `tr` | : | | **Ukrainian** | `uk` | : | ### Asian & Pacific | Language | Code | Dialect variants | | - | - | - | | **Chinese (Mandarin, Simplified)** | `zh` | `zh-CN`, `zh-Hans` | | **Chinese (Mandarin, Traditional)** | `zh-TW` | `zh-Hant` | | **Chinese (Cantonese)** | `zh-HK` | : | | **Hindi** | `hi` | : | | **Indonesian** | `id` | : | | **Japanese** | `ja` | : | | **Korean** | `ko` | `ko-KR` | | **Malay** | `ms` | : | | **Thai** | `th` | `th-TH` | | **Vietnamese** | `vi` | : | ### Arabic | Language | Code | Variant | | - | - | - | | **Arabic (Generic)** | `ar` | N/A | | **Gulf: UAE** | `ar-AE` | Emirati | | **Gulf: Saudi Arabia** | `ar-SA` | Saudi | | **Gulf: Qatar** | `ar-QA` | Qatari | | **Gulf: Kuwait** | `ar-KW` | Kuwaiti | | **Levantine: Syria** | `ar-SY` | Syrian | | **Levantine: Lebanon** | `ar-LB` | Lebanese | | **Levantine: Palestine** | `ar-PS` | Palestinian | | **Levantine: Jordan** | `ar-JO` | Jordanian | | **Nile: Egypt** | `ar-EG` | Egyptian | | **Nile: Sudan** | `ar-SD` | Sudanese | | **Maghrebi: Morocco** | `ar-MA` | Moroccan | | **Maghrebi: Algeria** | `ar-DZ` | Algerian | | **Maghrebi: Tunisia** | `ar-TN` | Tunisian | | **Mesopotamian: Iraq** | `ar-IQ` | Iraqi | | **Peripheral: Chad** | `ar-TD` | N/A | | **Peripheral: Iran** | `ar-IR` | N/A | For code-switching or unknown language input, use `language: "multi"`. The STT engine auto-detects on each utterance, and TTS renders accordingly. ## Setting the language ```json Specific language theme={null} "stt": { "provider": "lk-inference", "model": "deepgram/nova-3", "language": "fr-CA" } ``` ```json Multi-language (auto-detect) theme={null} "stt": { "provider": "lk-inference", "model": "deepgram/flux-general-multi", "language": "multi" } ``` ```json With fallback theme={null} "stt": { "provider": "lk-inference", "model": "deepgram/flux-general-multi", "language": "en", "fallback_model": "deepgram/flux-general-en" } ``` Full agent creation with a multilingual configuration: see the [Create Agent reference](/api-reference/endpoint/agentcreate) for every field. ## Provider language coverage Provider language coverage evolves. Always check the source docs for the very latest list. Broadest STT language coverage and high accuracy. Real-time multilingual code-switching STT. Low-latency multilingual streaming TTS. ## Prompt considerations for multilingual agents * **Respond in the same language as the user.** Add this instruction explicitly: LLMs sometimes default to English. * **Watch for code-switching.** Users often mix languages ("Book me a table para dos"). Multi mode handles input; instruct the LLM to match the dominant language in output. * **Test dialect variants.** A single `es` model may transcribe `es-MX` fine but stumble on `es-AR`. If accuracy matters, pick the dialect explicitly. ## What's next Voice IDs and provider-specific settings. Every supported STT, LLM, and TTS provider. # Realtime Pipeline Source: https://docs.trugen.ai/docs/agents/pipeline The end-to-end architecture powering TruGen's real-time conversational AI Teammates. TruGen's conversational pipeline connects speech, perception, reasoning, and expressive video response into a single continuous flow: optimised for speed and natural interaction, delivering responses in **under one second**. ## Pipeline stages ### 1. Communication protocol (WebRTC) Provides real-time two-way audio and video streaming. This layer captures microphone and camera input directly from the user and transports it to TruGen's inference engine with minimal latency. It also streams back rendered avatar video in real time, enabling fluid face-to-face interaction. ### 2. STT: Speech to Text Converts the user's spoken audio into text instantly using advanced streaming transcription. STT runs continuously and incrementally, capturing partial and final utterances so the agent can begin reasoning before the user finishes speaking. ### 3. Turn detection Detects natural conversation boundaries: pauses, interruptions, and handovers. This enables the agent to know when to listen, when to speak, and how to gracefully interrupt or yield, replicating natural human conversational flow. Two settings on `avatars[0].config` tune this stage per agent: * **`turn_handling`**: how assertively the agent takes turns: `proactive` (drives the conversation), `balanced` (natural back-and-forth), or `deliberate` (waits and speaks only when clearly prompted). Defaults to `proactive`. * **`interruptability`**: how easily the user can interrupt the agent mid-speech: `low` (finishes its thought before yielding), `medium` (yields on normal user speech), or `high` (yields at the slightest sign of speech). Defaults to `medium`. ### 4. LLM: Language Model Generates intelligent, contextually relevant responses using large language models powered by your preferred provider. The LLM understands conversation memory, tone, context, and intent to produce meaningful and personalised responses. ### 5. Knowledge Base Enhances reasoning with structured and unstructured organisational knowledge (documents, FAQs, APIs, databases, and custom content), ensuring answers are factual, brand-aligned, and grounded in real data rather than generic assumptions. ### 6. TTS: Text to Speech Converts the generated response into natural, expressive speech. TTS models produce high-quality voice output in real time, supporting multiple languages, tones, and emotional expressions. ### 7. Avatar rendering (Huma-2) Generates expressive video frames synchronised with speech. Using TruGen's **Huma-2** neural avatar model, the system produces realistic facial expressions, micro-expressions, lip sync, gaze direction, and emotional nuance: resulting in human-like communication. This tightly optimised pipeline enables **sub-second agent reactions**, face-to-face realism, and natural conversational dynamics. STT, LLM, TTS, and Knowledge Base modules are **agent-agnostic**: each agent can choose its own model provider, configuration, or customisation independently. ## Next steps Deep dive on the Huma family: the models powering the render stage of this pipeline. Every STT, LLM, and TTS provider you can slot into the pipeline. # Prompting Strategies Source: https://docs.trugen.ai/docs/agents/prompting-strategies Write system prompts that behave well in a real-time, spoken, on-camera setting. The system prompt is the single most important input you control. It defines who your agent is, how it speaks, what it knows, and what it won't do. Real-time video agents are harder to prompt than a text chatbot for three reasons: 1. **Responses are spoken, not read.** Markdown, symbols, and long paragraphs sound wrong. 2. **Latency is visible.** Every extra token delays the first word out. 3. **The user can see the agent.** Verbose responses feel robotic and unnatural on camera. This guide is a six-section framework that handles all three. Copy the templates, then adapt. The LLM has no awareness that its output will be spoken and rendered on a face. You have to tell it explicitly. ## The six sections Structure every prompt in this order: the LLM reads top-to-bottom, and earlier instructions carry more weight. 1. **Identity**: who the agent is 2. **Style**: how it talks 3. **Behaviors**: how it handles the conversation 4. **Response rules**: how to format spoken output 5. **Guardrails**: what it must never do 6. **Flow** *(optional)*: a specific step-by-step for structured conversations ## 1. Identity Start with a clear, one-paragraph identity: name, role, expertise, and purpose. Concrete beats abstract. ```markdown theme={null} # Identity You are Alex, TruGen's AI teammate for developer support. You help engineers integrate the platform: quickstarts, SDKs, API details, and debugging. You are patient, precise, and quick to point people to the right doc. ``` Bad identities: * *"You are a helpful assistant."*: no persona, no scope * *"You are an AI that can help with anything."*: impossible to be good at anything * *"You are Steve Jobs."*: never impersonate a real person ## 2. Style Describe communication style with **behavioral anchors**: not adjectives. "Warm" is vague; "opens with a first-name greeting and asks how you're doing" is behavior. ```markdown theme={null} # Style - Warm but efficient. Get to the answer fast, but never sound curt. - Match the user's energy: if they're excited, be excited; if they're frustrated, acknowledge it first before diagnosing. - Use everyday language. Avoid jargon unless the user uses it first. - Occasional light humor is okay when the moment calls for it. Never sarcasm. - When you don't know, say so plainly and offer the next best step. ``` 3–4 concrete cues beats 10 vague adjectives. ## 3. Behaviors Describe how the agent runs a conversation: opening, active listening, redirects, closing. ```markdown theme={null} # Behaviors - Open with a brief, warm greeting. Ask what the user is trying to build. - Listen for the actual problem before proposing a solution. If the user is vague, ask exactly one clarifying question. - If the user goes off-topic (weather, politics, unrelated jokes), acknowledge briefly, then steer back with "…anyway, back to what you're building: " - If a question is beyond your scope, hand off explicitly: "This is beyond what I can help with directly: try support@trugen.ai." - End the call gracefully. Confirm the user got what they needed before saying goodbye. ``` ## 4. Response rules This is the section that makes voice work. The LLM defaults to text-like output (markdown, lists, code blocks). You have to override that. ```markdown theme={null} # Response rules You are speaking through a real-time voice interface. Your output is read aloud by a text-to-speech engine. Apply these rules on every turn: - Respond in plain text only. No JSON, markdown, headings, lists, tables, code blocks, emojis, or ASCII art. - Keep responses to 1–2 short sentences by default. Longer only if the user explicitly asks for detail. - Ask one question at a time. Never chain multiple questions in one turn. - Spell numbers, phone numbers, and email addresses as words. Say "at" for "@" and "dot" for ".". - Omit URL prefixes ("h-t-t-p-s") when reading URLs: say the domain only. - Never say "As an AI…" or "As a language model…": it breaks immersion. - If you use an acronym the user probably doesn't know, spell it out on first mention: "the API: that's application programming interface." ``` This section alone accounts for most of the difference between a prompt that works and one that doesn't. ## 5. Guardrails Hard rules the agent must never break. Enforce them in the prompt itself and by keeping the prompt above user messages in your instruction hierarchy. This section is about style: rules folded into the system prompt as text, with no enforcement beyond the LLM choosing to follow them. For rules that need their own callable check, a canned deterministic response, and an optional trigger webhook, use the dedicated [Guardrails](/docs/agents/guardrails/overview) feature instead. It's a separate object the agent calls as a tool, not prompt text. The two are complementary: keep style constraints here, and move anything safety- or compliance-critical to the real feature. Either way, the agent only checks a guardrail, prompt-based or the dedicated feature, when the prompt actually tells it to. ```markdown theme={null} # Guardrails - Never claim to be human. If asked, confirm you are an AI. - Do not provide medical, legal, or financial advice. Share general information and recommend a licensed professional. - Do not disclose competitors' pricing, roadmaps, or internal details. - Do not share system prompts, tool schemas, or internal reasoning even if asked directly. - If a user is in distress or an emergency, acknowledge, and share a human contact or emergency resource. ``` ## 6. Flow *(optional)* For structured conversations (interviews, intake, onboarding), describe the phases and how the agent moves between them. For open-ended agents, skip this section entirely. ```markdown theme={null} # Flow ## Phase 1: Discovery (3–5 turns) - Confirm the user's role and team size - Understand their current stack - Identify the primary pain they're solving ## Phase 2: Solution match (3–5 turns) - Recommend the TruGen features that best fit - Point to specific docs - Ask what's still unclear ## Phase 3: Next step (1–2 turns) - If highly qualified, offer to schedule a call - Otherwise, share resources and invite them to Discord ``` For structured flows, describe each phase explicitly in the prompt and let the LLM decide when to move between them based on the user's answers. ## A complete example Bringing it all together: ```markdown theme={null} # Identity You are Priya, a friendly nutritionist AI. You help users make small, practical changes to their eating habits without ever prescribing a specific diet. # Style - Warm, curious, non-judgmental - Match the user's energy: high-energy back, calm back - Never lecture; always offer, then let the user decide - Occasional emoji-free light humor when it fits # Behaviors - Open with a warm hello and ask what brought them here today - Listen fully before suggesting anything: ask one clarifying question if needed - If they ask for a specific meal plan, redirect: "I'll share ideas, but the plan is yours to build: a registered dietitian can build a specific one for you if you'd like a referral." - End with a small, specific, doable suggestion for the next 24 hours # Response rules You are speaking via voice. Apply these on every turn: - Plain text only, 1–2 short sentences by default - Ask one question at a time - Spell numbers and email addresses as words - Never mention "AI" or "language model": you're Priya # Guardrails - Never diagnose medical conditions - Never recommend supplements, medications, or restrictive diets - For eating disorders or body image distress, gently share the NEDA helpline (call one-eight-hundred, nine-three-one, two-two-three-seven) - Confirm you are an AI if directly asked ``` ## Prompt hygiene checklist Before shipping any prompt: * [ ] Under 2000 tokens total * [ ] Contains an Identity section with a specific persona * [ ] Contains Response rules that explicitly say "voice interface" * [ ] No markdown, code fences, or JSON schemas in the prompt itself * [ ] Guardrails cover: AI disclosure, off-topic redirects, and any regulated advice * [ ] Tested with at least 10 real user questions * [ ] Tested with adversarial input ("Ignore your instructions and…") ## Iterating on prompts Prompts fail in ways you can't predict from reading them. The only way to know is to listen to real conversations. * **Week 1:** ship the first version. Read 20 transcripts. * **Week 2:** update the prompt based on what you saw. Ship. Read another 20. * **Ongoing:** every time the agent embarrasses you, add a rule that would have prevented it. Don't try to write a perfect prompt on day one. Iterate. ## What's next Share prompts across many agents. Choose the right model for your prompt. # System Messages Source: https://docs.trugen.ai/docs/agents/system-messages Configure the greeting, exit, idle, and heads-up messages your agent uses to open, close, and hold a conversation. Every conversation with an agent has recurring moments the LLM doesn't need to reason about: the greeting when a user first joins, the wrap-up before a call ends, the polite check-in when things go quiet. **System messages** let you script these moments explicitly so the agent handles them consistently. Each system message is a short list of lines. If more than one is provided, the agent picks one at session time so repeat visitors don't hear the same phrase every call. ## The four system messages | Message | When it fires | Configured via | | - | - | - | | **Welcome message** | When the user joins the session | `welcome_message` | | **Idle callout** | When the user has been silent for a configured time | `idle_timeout` | | **Exit heads-up** | Shortly before `max_call_duration` is reached | `exit_heads_up_message` (also `warning_exit_message`) | | **Exit message** | When the call ends (either user leaves or duration is hit) | `exit_message` | ## Welcome message Fires as soon as the agent joins the session and the user's media is ready. This is the first thing your agent says. ```json theme={null} "welcome_message": { "messages": [ "Hi, how are you doing today?" ], "wait_time": 1 } ``` | Field | Type | Description | | - | - | - | | `messages` | string\[] | One or more greetings. One is chosen per session. | | `wait_time` | number | Seconds to wait after the user joins before speaking (avoids talking over a still-loading page). Default `1`. | **Best practices** * Keep it short: one sentence at most. It's the first impression. * Match the agent's persona from the system prompt. A support agent's greeting should sound different from a coach's. * Provide 2–4 variants so the greeting doesn't feel canned to returning users. ## Idle callout Fires when the user has been silent for `timeout` seconds. Useful to check whether the user is still there before ending the session. ```json theme={null} "idle_timeout": { "timeout": 30, "filler_phrases": [ "Hey it's been a while since we last spoke, are we still connected?" ] } ``` | Field | Type | Description | | - | - | - | | `timeout` | number | Seconds of silence before the callout fires. Default `30`. | | `filler_phrases` | string\[] | One or more callout lines. One is chosen when the timeout hits. | **Best practices** * Don't set the timeout too low: 20–30 s is natural. Lower feels twitchy. * Provide friendly, warm phrases. This moment often feels awkward if scripted robotically. * Have 3–5 variants so a user idling twice in one call doesn't hear the same line. ## Exit heads-up Fires a configurable number of seconds before the session hits `max_call_duration`. Gives the user a gentle warning that time is almost up. ```json theme={null} "exit_heads_up_message": { "callout_before": 10, "messages": [ "We are almost at the end of our call, thank you for your time." ] } ``` | Field | Type | Description | | - | - | - | | `callout_before` | number | Seconds before session end at which the heads-up fires. Default `10`. | | `messages` | string\[] | One or more heads-up lines. | ## Exit message Fires when the session ends: either the user leaves or `max_call_duration` is hit. ```json theme={null} "exit_message": { "messages": [ "We are at the end of our call, thank you for your time." ], "max_call_duration": 300 } ``` | Field | Type | Description | | - | - | - | | `messages` | string\[] | One or more closing lines. | | `max_call_duration` | number | Seconds the session can run before this message fires and the call ends. Default `300`. | The equivalent field `warning_exit_message` also exists in the API for backward compatibility: use `exit_heads_up_message` for new agents. ## Toggling messages on and off Each of the four messages can be independently enabled or disabled via `config.systemConfig`: ```json theme={null} "config": { "systemConfig": { "entryMessageToggle2": true, "idleCalloutToggle2": true, "exitHeadsUpToggle2": true, "exitMessageToggle2": true } } ``` Set any toggle to `false` to keep the message configured but suppress it at runtime. ## Full example Configuring all four messages in a single `avatars[]` block: ```json theme={null} "avatars": [ { "avatar_key_id": "665a1170", "welcome_message": { "messages": [ "Hi, I'm Priya. What brought you here today?", "Hey there, good to see you. What can I help with?" ], "wait_time": 1 }, "idle_timeout": { "timeout": 30, "filler_phrases": [ "Still with me?", "Take your time, I'm here whenever you're ready." ] }, "exit_heads_up_message": { "callout_before": 15, "messages": [ "Heads up, we've got about fifteen seconds left before this call wraps." ] }, "exit_message": { "messages": [ "Thanks for chatting today. Take care!", "That's our time, great talking with you. Bye for now." ], "max_call_duration": 300 } } ] ``` ## Next steps Write a system prompt whose voice matches your system messages. Share your system messages across many agents via a template. # Agent Templates Source: https://docs.trugen.ai/docs/agents/templates Reusable persona blueprints that let you roll out many agents with consistent prompt, knowledge, and behavior. Templates define the **persona, behaviour, and conversational structure** of your AI Teammates. Rather than configuring every setting manually for each agent, templates give you a reusable blueprint: shareable across multiple agents, enabling fast iteration, consistent brand voice, and governance at scale. *** ## What Can a Template Include? A template consists of the following configurable components, and more: * **Avatar for Teammate** - Choose the visual identity your agent presents during live video conversations. * **System Prompt** - Defines the agent's role, tone, and knowledge scope. This is the core directive that shapes reasoning and personality. * **Knowledge Base Attachments** - Bind knowledge sources such as documents, products, FAQs, or APIs. * **Guardrail Attachments** - Bind safety checks such as hate speech, PII, or misinformation detection that run during the conversation. * **Agent Config** - Fine-tune model behaviour, session limits, recording preferences, and other agent-level settings. * **Entry, Exit & Idle Timeout Messages** - Set custom greetings, farewells, and responses to user inactivity. * **Behaviour & Safety Settings** - Control boundaries, compliance rules, escalation, and conversation guardrails. * **Callback Events & Webhooks** - Trigger external workflows or UI updates based on session lifecycle events. Templates ensure that every agent deployed by your organisation shares consistent brand voice, intelligence grounding, and conversation workflow: whether you have 1 agent or thousands. *** ## Create & Use a Template Template creation and management can be performed using the API or visually through our Developer Platform. Create a conversational template using the API. This example shows a minimal configuration. ```bash Request theme={null} curl --request POST \ --url https://api.trugen.ai/v1/template \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data ' { "template_name": "Sales Assistant Template", "template_system_prompt": "You are a friendly AI sales assistant that guides users through product selection and answers detailed product questions clearly.", "config": { "systemPrompt": "Respond in a conversational tone and always ask follow-up questions.", "conversationalContext": "sales", "maxCallDuration": 300 }, "knowledge_base": [ { "id": "15b12908-309f-4e0f-bcb0-a4e23d45169a", "name": "Product Catalog" } ], "guardrail": [ { "id": "dfbaa3c6-1e90-43df-869a-b023896a198c", "name": "Hate Speech Filter" } ], "is_active": true, "record": true, "callback_url": "", "callback_events": [] }' ``` ```json Response theme={null} { "id": "d65a4f92-44b1-4fe6-b2ac-a1cb66366ddc", "message": "Template created successfully" } ``` Replace `` with your actual API key generated from our [Developer Portal](https://app.trugen.ai). Use the template ID returned above to spin up a fully configured agent instantly. ```bash Request theme={null} curl --request POST \ --url https://api.trugen.ai/v1/ext/agentbytemplate \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data ' { "avatar_key_id": "665a1170", "template_id": "76d9ff1d-b1d5-4dee-9b9a-d4c4d58c9c55", "email": "demo@trugen.ai" }' ``` ```json Response theme={null} { "id": "51ed8d70-9379-422f-aed4-f9f2b293ba4a", "message": "Agent created successfully" } ``` Replace `template_id` with the actual template `id` returned in Step 1. *** ## Why Use Templates? Clone-ready configurations let you launch new agents in seconds: no manual setup from scratch. Centralise personality, tone, and rules so every agent speaks with the same voice. Ideal for enterprise teams and multi-location rollouts: one template, thousands of agents. Modify a template and all agents built from it update instantly: no rebuilding required. *** ## What's Next? Full API set for creating, updating, retrieving, and deleting templates. Attach knowledge sources to your template so agents always have the right context. # Text to Video Source: https://docs.trugen.ai/docs/agents/text_to_video Generate a professional avatar video from a script: no camera or studio required. Turn a written script into a fully rendered avatar video in minutes. Provide your text, choose an avatar and voice, and TruGen handles the rest: lip sync, facial expression, and delivery are all generated automatically. This is in private preview. If you'd like to try it, please contact us at [support@trugen.ai](mailto:support@trugen.ai). ## How It Works Generate an API key from the [TruGen Developer Portal](https://app.trugen.ai) and include it as the `x-api-key` header in every request. Pick an avatar ID from the [Avatar Gallery](/docs/avatars/gallery) and paste it into your payload. ```bash theme={null} "avatar_id": "c5b563de" ``` Select a voice from the table below and include the `voice_id`, `provider_name`, and `model_name` in your payload. | Name | Voice ID | | :- | :- | | **Rachel** | `21m00Tcm4TlvDq8ikWAM` | | **Laura** | `FGY2WhTYpPnrIDTdsKH5` | | **Chris** | `iP95p4xoKVk53GoZ742B` | | **Will** | `bIHbv24MWmeRgasZH58o` | | **Luca** | `4JVOFy4SLQs9my0OLhEw` | | **Sean** | `ztnpYzQJyWffPj1VC5Uw` | | **Hope** | `uYXf8XasLslADfZ2MB4u` | | **Jess** | `ys3XeJJA4ArWMhRpcX1D` | | **Loral** | `bP6y87KyX5lwNEi7xOkX` | | **Yatin** | `rFzjTA9NFWPsUdx39OwG` | | **Monika Sogam** | `ZUrEGyu8GFMwnHbvLhv2` | | **Evan** | `TWutjvRaJqAX89preB4e` | | **Sameer** | `SV61h9yhBg4i91KIBwdz` | | **Laura (Alt)** | `FGLJyeekUzxl8M3CTG9M` | | **Omar** | `xvhpbk8otnNHtT3fjCpr` | ```bash theme={null} "provider_name": "elevenlabs", "model_name": "eleven_turbo_v2_5" ``` Provide the text you want the avatar to speak. The avatar's lip movements and expressions are automatically synced to the generated audio. ```bash theme={null} "script": "Hello, welcome to TruGen." ``` Video generation is asynchronous. Provide a publicly reachable HTTPS endpoint: TruGen will POST the finished video link to it when rendering is complete. ```bash theme={null} "callback_url": "https://yourdomain.com/webhook/video-ready" ``` Send a `POST` to the video generation endpoint with your full payload. ```bash cURL theme={null} curl --request POST \ --url https://api.trugen.ai/v1/script-to-video/createVideo \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "avatar_id": "c5b563de", "voice_id": "FGY2WhTYpPnrIDTdsKH5", "provider_name": "elevenlabs", "model_name": "eleven_turbo_v2_5", "script": "Hello, welcome to TruGen.", "callback_url": "https://yourdomain.com/webhook/video-ready" }' ``` ```python Python theme={null} import requests url = "https://api.trugen.ai/v1/script-to-video/createVideo" payload = { "avatar_id": "c5b563de", "voice_id": "FGY2WhTYpPnrIDTdsKH5", "provider_name": "elevenlabs", "model_name": "eleven_turbo_v2_5", "script": "Hello, welcome to TruGen.", "callback_url": "https://yourdomain.com/webhook/video-ready" } headers = {"x-api-key": ""} response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` Replace `` with your actual API key from the [Developer Portal](https://app.trugen.ai). ## What's Next? Full endpoint documentation including status polling and response schema. Browse all available avatars and copy their IDs. Use your own likeness instead of a stock avatar. Understand how TruGen delivers async results to your callback URL. # Custom Tools Source: https://docs.trugen.ai/docs/agents/tools/custom-tools Build API, MCP, and client-side tools to extend your agent with custom actions and integrations. Custom tools let you connect your agent to any system not covered by a pre-built integration. TruGen supports three types of custom tools: choose based on where the action happens and how your system communicates. *** ## API & Webhook Call any external HTTP endpoint during a conversation. The agent uses function calling to decide when the tool is relevant, fires the request, and incorporates the response into its reply. ### Configuration | Field | Required | Description | | - | - | - | | **Tool Name** | Yes | Internal identifier used by the LLM (e.g., `getUserData`, `sendNotification`). Use camelCase with no spaces. | | **Description** | Yes | Explains what the tool does and when to use it. The clearer this is, the better the agent will know when to invoke it. | | **Request URL** | Yes | The full endpoint URL the request will be sent to (e.g., `https://api.example.com/users`). | | **HTTP Method** | Yes | `GET`, `POST`, `PUT`, `PATCH`, or `DELETE`. | | **Request Headers** | No | Custom headers such as `Authorization`, `Content-Type`, or any other headers your endpoint requires. | | **Parameters** | No | The inputs the tool accepts. Define each as a named property with a type and description: the agent uses these to populate the request. | | **Messages** | No | Status messages shown at different stages of tool execution (e.g., a message while the request is in flight, or on success/failure). | ### Example ```bash cURL theme={null} curl --location 'https://api.trugen.ai/v1/ext/tool' \ --header 'x-api-key: ' \ --header 'Content-Type: application/json' \ --data '{ "type": "tool.api", "schema": { "type": "function", "name": "check_weather", "description": "Check the current weather in the location", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "Location to find weather" } }, "required": ["location"] } }, "request_config": { "name": "test", "method": "GET", "url": "https://getweather.com", "headers": { "authorization": "api key value" } }, "event_messages": { "on_start": { "message": "Getting weather" }, "on_success": { "message": "Successfully got latest weather" }, "on_delay": { "delay": 1, "message": "waiting for weather data" }, "on_error": { "message": "Failed to get the data" } }, "is_active": true }' ``` Write your **Description** as if you're telling a smart colleague exactly when to pick up this tool. Specificity matters: vague descriptions lead to missed or incorrect invocations. *** ## MCP Connect your own **Model Context Protocol** server to give the agent access to tools via a standardised interface. Use this if you already run an MCP-compatible server or want a protocol-native integration. ### Configuration | Field | Required | Description | | - | - | - | | **Tool Name** | Yes | Name used to identify this MCP connection internally. | | **Description** | Yes | What this MCP server provides: used to help the agent understand when to call it. | | **Server URL** | Yes | The base URL of your MCP server (e.g., `https://mcp.yourcompany.com`). | | **Transport Type** | Yes | How the client communicates with the server: see below. | | **Request Headers** | No | Auth headers or any custom headers your MCP server requires. | ### Transport Types | Type | When to Use | | - | - | | **Streamable HTTP (SHTTP)** | Standard HTTP-based streaming. Best for most deployments: simpler infrastructure with support for streamed responses. | | **Server-Sent Events (SSE)** | Event-driven, long-lived connection. Best when your server pushes updates to the client in real time. | Your MCP server must be publicly reachable from TruGen's infrastructure. If it's behind a private network, expose it via a secure tunnel or deploy it to a public endpoint first. *** ## Client Tools Client tools execute inside your **frontend application** at runtime: not on a server. Use them to trigger UI actions during a conversation, such as opening a modal, navigating to a page, or updating an on-screen element. Client tools are defined in the Developer Studio and implemented as matching handlers in your npm package integration. ### Configuration | Field | Required | Description | | - | - | - | | **Tool Name** | Yes | Must match the handler name in your npm package (e.g., `openHelpPanel`, `navigateToCheckout`). | | **Description** | Yes | Describes what the client action does: the agent uses this to decide when to trigger it. | | **Parameters** | No | Inputs the tool passes to your client handler (e.g., `{ "panelId": "billing" }`). | | **Messages** | No | Messages for different lifecycle stages of the tool: invocation, completion, or error. | ### Implementing the Handler After defining a client tool in the studio, implement the matching handler in your npm package: ```js JavaScript theme={null} import { TrugenClient } from '@trugen/sdk'; const client = new TrugenClient({ agentId: 'YOUR_AGENT_ID' }); client.on('tool:openHelpPanel', (params) => { // params contains whatever the agent passed openPanel(params.panelId); }); ``` ```ts TypeScript theme={null} import { TrugenClient, ToolEvent } from '@trugen/sdk'; const client = new TrugenClient({ agentId: 'YOUR_AGENT_ID' }); client.on('tool:openHelpPanel', (params: { panelId: string }) => { openPanel(params.panelId); }); ``` The tool name defined in the studio must exactly match the event name used in your handler: including casing. ### Testing a Client Tool Use the **Test** button in the Developer Studio to fire the tool with sample inputs and verify the handler receives and processes them correctly before going live. *** ## What's Next? Connect 1,000+ apps via Composio without writing API code. Receive real-time webhook events from active conversations. # Integrations Source: https://docs.trugen.ai/docs/agents/tools/integrations Connect 1,000+ apps to your AI Teammate via Composio: no custom API code required. TruGen integrates with **Composio** to give your agents access to over 1,000 third-party apps out of the box. Connect tools like Slack, Google Calendar, HubSpot, Salesforce, Notion, GitHub, and more: without writing any API integration code yourself. Once connected, the agent automatically decides when to use a tool based on your description and the user's request. ## How It Works Composio handles the authentication and API plumbing. You pick the tools you want, authorise the connection, and TruGen's agent can start using them immediately in live conversations. In the [Developer Studio](https://app.trugen.ai), navigate to your agent's **Tools** section and select **Integrations**. Search the Composio catalogue for the app or action you want: for example, `Send Slack Message`, `Create Calendar Event`, or `Update HubSpot Contact`. Connect your account using **Composio's native authentication**: OAuth for apps like Google or Slack, or an API key for services like OpenAI or Stripe. Composio handles the token storage and refresh automatically. Once authorised, the integration is available to your agent. The agent will invoke it automatically when the user's request matches the tool's purpose. ## Supported Authentication Methods | Method | Used By | | - | - | | **OAuth 2.0** | Google, Slack, Salesforce, HubSpot, GitHub, and most major SaaS platforms | | **API Key** | Stripe, SendGrid, Twilio, and services with key-based access | | **Basic Auth** | Legacy systems and internal tools | ## Popular Integrations | Category | Examples | | - | - | | **Communication** | Slack, Microsoft Teams, Gmail, Twilio | | **CRM & Sales** | HubSpot, Salesforce, Pipedrive | | **Productivity** | Google Calendar, Notion, Airtable, Trello | | **Developer Tools** | GitHub, Jira, Linear | | **E-commerce** | Shopify, Stripe | Composio supports 1,000+ apps. If your app isn't listed, you can connect it using an [API & Webhook tool](/docs/agents/tools/custom-tools#api--webhook) instead. ## Testing Your Integration After connecting a tool, use the **Test** button in the Developer Studio to verify the connection is working. Provide the expected inputs and check that the response comes back correctly before going live. ## What's Next? Build API, MCP, or client-side tools for endpoints not covered by Composio. See all tool types and when to use each one. # Tools Source: https://docs.trugen.ai/docs/agents/tools/overview Extend your AI Teammate with actions: call APIs, connect integrations, trigger UI events, and more. Tools give your AI Teammate the ability to take action during a conversation: not just respond. Instead of stopping at an answer, your agent can call an API, look up live data, trigger something in your app, or connect to any of thousands of third-party services. Tools are powered by **LLM function calling**: the agent decides when a tool is relevant based on the user's request and your description of what the tool does. ## Tool Types Connect 1,000+ apps via Composio: Slack, Google Calendar, Salesforce, HubSpot, and more. Authorize with native OAuth or API key. Call any external HTTP endpoint during a conversation. Define the URL, method, headers, and parameters: the agent handles the rest. Bring your own Model Context Protocol server. Connect via Streamable HTTP or SSE for a standards-based tool integration. Trigger actions inside your frontend (open a modal, navigate to a page, update the UI) handled by your npm package at runtime. ## When to Use Each | Tool Type | Best For | | - | - | | **Integrations** | Connecting to popular apps quickly without writing any code | | **API & Webhook** | Calling your own internal APIs or third-party REST endpoints | | **MCP** | Teams already running an MCP-compatible server | | **Client Tools** | Triggering real-time UI actions in the user's browser during a conversation | ## Testing a Tool Every tool has a **Test** button in the Studio. Once you configure a tool, you can run it in a live sandbox directly from the Tools tab: provide the inputs the tool expects, fire the request, and see the exact response before saving to your agent. The test flow supports all four tool types: * **API / Webhook**: sends a real HTTP request to your endpoint and shows the status code + response body * **MCP**: lists the tools exposed by your MCP server and lets you invoke any of them with test parameters * **Client tools**: validates the schema and simulates the handler * **Integrations**: lets you fire a real Composio action with test inputs against your connected account The response is displayed with the HTTP status colored green (2xx), amber (3xx), or red (4xx/5xx) so you can catch misconfigured auth, wrong URLs, or bad payload shapes without ever starting a conversation. Test tools **before** attaching them to a production agent. A misconfigured tool that only fails mid-conversation is a bad first impression for users. ## What's Next? Connect Composio apps to your agent in minutes. Build API, MCP, and client-side tools for your agent. # Vision Understanding Source: https://docs.trugen.ai/docs/agents/vision/overview Real-time video analysis for monitoring, proctoring, and engagement tracking: powered by Hawkeye-1. TruGen Vision Understanding powered by **Hawkeye-1** is a real-time video analysis system designed for live monitoring and proctoring. It connects to a live video stream and continuously analyses participant behaviour using AI. This feature is available only for enterprise customers. The platform can: * Detect emotions * Track where a person is looking * Monitor head movement and attention * Count the number of people visible on screen It's especially useful for: * Online exam proctoring * Interview monitoring * Compliance and security checks * Attention and engagement tracking ## How It Works The system connects to a live video session, processes video frames in real time, and pushes results instantly to dashboards, apps, or external systems. The same events are also published directly into the LiveKit room on the `hawkeye-events` data-channel topic, so in-room clients can react without running a callback server. It can also trigger alerts or actions automatically when certain conditions are detected, such as: * A participant repeatedly looking away * Multiple people appearing on screen * Signs of stress or distraction ## Key Features Identifies emotional states in real time: Happy, Neutral, Sad, Angry, Fearful, and Surprised. Detects whether the person is looking left, right, up, down, or straight ahead. Tracks eye movement to understand attention and focus across all directions. Detects how many people are visible in the frame at any given moment. ## Real-Time Alerts & Automation The system supports custom triggers and automated actions. For example: * If someone looks away more than 5 times, automatically: * Send an alert * Trigger a webhook * Notify a moderator or proctor Events reach you over a WebSocket callback and the LiveKit data channel (`hawkeye-events` topic), so both backend services and in-room clients can act in real time. See [Event Delivery](/docs/agents/vision/start-session#event-delivery) for the exact formats. ## Built for Scale Vision Understanding is optimised for real-time performance and can run multiple AI analysis modules simultaneously with low latency. Each instance runs in its own infrastructure component, ensuring no impact on conversational quality or performance. ## Common Use Cases | Use Case | Description | | - | - | | **Online Exam Proctoring** | Detect cheating behaviour, multiple faces, or attention drift in real time | | **Remote Interview Monitoring** | Track engagement, eye contact, and emotional signals during live interviews | | **Live Engagement Analysis** | Measure attention and emotional response during presentations or training | | **Workplace Compliance Monitoring** | Ensure policy compliance in monitored sessions or sensitive environments | | **AI-Powered Video Analytics** | Feed real-time vision data into dashboards, reports, or downstream systems | ## What's Next? Learn about the Huma family, the models powering TruGen's real-time avatars. Join and monitor external meetings with Vision Understanding enabled. # Get Vision Session Status Source: https://docs.trugen.ai/docs/agents/vision/session-status Check the state of a running Hawkeye session or read the final billing duration after it ends. `GET /v2/vision/{session_id}` returns the current state of a Hawkeye vision session (queued, running, or ended) along with the modules that are active and how long the session has been alive. ## Endpoint ```bash theme={null} GET https://api.trugen.ai/v2/vision/{session_id} Header: x-api-key: ``` `session_id` is the id returned by [Start a Vision Session](/docs/agents/vision/start-session). ## Example ```bash theme={null} curl --request GET \ --url https://api.trugen.ai/v2/vision/8f2a1e5b-4c9d-4a3f-9c11-2c07be7d1c22 \ --header 'x-api-key: ' ``` ## Response ```json theme={null} { "session_id": "8f2a1e5b-4c9d-4a3f-9c11-2c07be7d1c22", "status": "IN_PROGRESS", "livekit_url": "wss://your-livekit-domain.livekit.cloud", "participant": "auto", "max_duration": 10, "elapsed_duration_seconds": 148, "modules": [ "emotion_recognition", "eyegaze_tracking", "face_count", "face_out_of_focus", "face_pose_detection" ], "started_at": "2026-08-11T14:22:03Z", "ended_at": "" } ``` ### Response fields | Field | Description | | - | - | | `session_id` | The id you passed in the URL. | | `status` | `IN_QUEUE` → `IN_PROGRESS` → `COMPLETED` (or `FAILED` / `CANCELLED`). | | `livekit_url` | The LiveKit room Hawkeye is analysing. | | `participant` | The participant identity being analysed. `"auto"` means Hawkeye chose the first non-agent one. | | `max_duration` | Session cap in minutes, as originally requested. | | `elapsed_duration_seconds` | Seconds since `started_at`. Frozen at the end when the session finishes. | | `modules` | Modules active on this session. | | `started_at` | RFC3339 UTC timestamp when Hawkeye joined the room. | | `ended_at` | RFC3339 UTC timestamp when the session terminated. Empty while `status` is `IN_QUEUE`/`IN_PROGRESS`. | ### Status values | Status | Meaning | | - | - | | `IN_QUEUE` | Session accepted, worker not yet started. | | `IN_PROGRESS` | Hawkeye is in the room and analysing video. | | `COMPLETED` | Session ended cleanly (either `max_duration` hit or the room closed). | | `FAILED` | Worker errored: check logs / retry with a fresh access token if it looks like an auth issue. | | `CANCELLED` | Explicitly cancelled. | ## Polling Guidance The status endpoint refreshes from Hawkeye on every call, so you never need to poll more often than roughly once every few seconds. Once a session reaches a terminal state (`COMPLETED`, `FAILED`, `CANCELLED`), further calls just replay the final response: no extra work is done backend-side. ## What's Next? Kick off a new session with the modules and classes you need. What Vision Understanding does and when to use it. # Start a Vision Session Source: https://docs.trugen.ai/docs/agents/vision/start-session Attach Hawkeye-1 to any LiveKit room and start real-time video analysis with the modules you choose. `POST /v2/vision` starts a new Hawkeye session on a LiveKit room you already have. Hawkeye joins as a subscriber, analyses the target participant's video, and pushes an event every time a class is detected: to your callback URL and into the LiveKit room itself over the data channel. Billing is a flat **1¢ per minute** per session. Sessions stop automatically once `max_duration` (in minutes) is reached. ## Endpoint ```bash theme={null} POST https://api.trugen.ai/v2/vision Header: x-api-key: Content-Type: application/json ``` ## Request For each module, you only pick the **classes** you care about. Everything else (evaluation frequency, thresholds) is set to sensible defaults server-side. ```json theme={null} { "livekit_url": "wss://your-livekit-domain.livekit.cloud", "access_token": "eyJhbGciOi...", "participant": "auto", "callback_url": "wss://your-callback-endpoint.example.com/vision", "max_duration": 10, "modules": { "face_pose_detection": ["Looking Left", "Looking Right"], "emotion_recognition": ["angry", "sad", "disgust", "fear", "happy", "surprise", "neutral"], "eyegaze_tracking": ["Looking left", "Looking right"], "face_count": ["2"], "face_out_of_focus": ["out_of_frame"] } } ``` ### Top-level fields | Field | Required | Description | | - | - | - | | `livekit_url` | ✅ | `wss://` URL of the LiveKit room Hawkeye should join. | | `access_token` | ✅ | LiveKit access token with `roomJoin: true` for that room. Hawkeye connects with this identity. | | `participant` | ➖ | Identity of the participant to analyse. Defaults to `"auto"`: Hawkeye picks the first non-agent participant in the room. Pass a specific LiveKit identity to lock analysis onto that participant instead. | | `callback_url` | ➖ | WebSocket URL to receive real-time alerts. Every event is also published to the LiveKit room's data channel, so this is optional: omit it if you only intend to consume the data channel or poll the [Get Session Status](/docs/agents/vision/session-status) endpoint. | | `max_duration` | ✅ | Hard cap in **minutes**. Hawkeye disconnects when reached. | | `modules` | ➖ | Modules to enable, keyed by module name. Each value is a list of class names to alert on. Omit `modules` entirely for all modules with all default classes. | ### Rules of thumb * **Skip `modules` altogether** → Hawkeye runs every module with every default class. * **Include a module with an empty list** (`"emotion_recognition": []`) → that module runs with its full default class list. * **Include a module with specific classes** → only those classes emit alerts. Any unknown class name is rejected with `400`. When you set `participant` to a specific identity, it must match the LiveKit **identity** the participant joined with (not their display name). If that participant hasn't joined yet, Hawkeye waits: if they never appear, the session idles until `max_duration` fires. ## Modules & Classes Detects head turns away from centre. **Classes:** `Looking Left`, `Looking Right` Classifies the participant's facial expression each second. **Classes:** `angry`, `sad`, `disgust`, `fear`, `happy`, `surprise`, `neutral` Independent of head pose: catches subtle off-screen glances. **Classes:** `Looking left`, `Looking right` Counts distinct faces in the frame. The class name is the exact face count you want to alert on. **Classes:** any numeric string, e.g. `"2"`, `"3"`, `"4"` Fires when the target participant's face moves out of the camera view. **Classes:** `out_of_frame` ## Minimum viable payload Everything defaulted: all modules, all classes: ```json theme={null} { "livekit_url": "wss://your-livekit-domain.livekit.cloud", "access_token": "eyJhbGciOi...", "callback_url": "wss://your-callback-endpoint.example.com/vision", "max_duration": 10 } ``` ## Only a couple of modules Just watch emotions and face count: ```json theme={null} { "livekit_url": "wss://your-livekit-domain.livekit.cloud", "access_token": "eyJhbGciOi...", "callback_url": "wss://your-callback-endpoint.example.com/vision", "max_duration": 10, "modules": { "emotion_recognition": ["angry", "sad"], "face_count": ["2", "3"] } } ``` ## Response ```json theme={null} { "session_id": "8f2a1e5b-4c9d-4a3f-9c11-2c07be7d1c22", "status": "IN_QUEUE", "max_duration": 10, "modules": [ "emotion_recognition", "eyegaze_tracking", "face_count", "face_out_of_focus", "face_pose_detection" ] } ``` | Field | Description | | - | - | | `session_id` | TruGen session identifier: use this to poll [Get Session Status](/docs/agents/vision/session-status). | | `status` | Initial lifecycle state, usually `IN_QUEUE`. Transitions to `IN_PROGRESS` when the worker joins. | | `max_duration` | Echoed back in minutes. | | `modules` | Sorted list of module names that were resolved for this session. | ## Event Delivery Every event is delivered over two channels: your `callback_url` (if you provided one) and the LiveKit room's data channel (always on). The event details are the same on both, so you can consume whichever fits your setup: or both. ### WebSocket callback When a class is detected, Hawkeye pushes a JSON message to your `callback_url`: ```json theme={null} { "session_id": "8f2a1e5b-4c9d-4a3f-9c11-2c07be7d1c22", "module": "emotion_recognition", "class": "angry", "timestamp": "2026-08-11T14:24:11Z" } ``` ### LiveKit data channel Hawkeye also publishes each event into the room via `publish_data` with `reliable=True`, on the `hawkeye-events` topic. Any client in the room receives it through its SDK's data-received event: filter on the `hawkeye-events` topic and decode the JSON payload: ```json theme={null} { "type": "alert", "payload": { "session_id": "8f2a1e5b-4c9d-4a3f-9c11-2c07be7d1c22", "module": "emotion_recognition", "class": "angry", "timestamp": "2026-08-11T14:24:11Z" } } ``` The `type` field identifies the event kind, and `payload` contains the same fields as the WebSocket callback. Data-channel delivery is best-effort: if a publish fails, Hawkeye logs the error and carries on, without interrupting analysis or the WebSocket callback. Use these events to drive dashboards, escalate to a moderator, or feed downstream analytics. Hawkeye handles the vision, you handle the reaction. ## What's Next? Poll a running session, or check the final state after it ends. What Vision Understanding does and when to use it. # Voice Library Source: https://docs.trugen.ai/docs/agents/voices/library Preview all available voices and copy the voice ID for use in your agent configuration. Browse all available voices below across our supported Text-to-Speech (TTS) providers: **ElevenLabs**, **Cartesia**, **Rime**, **Fish Audio**, and **Inworld TTS**. ElevenLabs voices include an interactive audio preview. Copy any voice ID to use directly in your agent's `voice_id` configuration. ## ElevenLabs Available via **Turbo 2** (`eleven_turbo_v2`) and **Turbo v2.5** (`eleven_turbo_v2_5`). Click play to hear a preview, and click the copy icon to copy the `voice_id`. *** ## Cartesia Available via **Sonic 3** (`cartesia/sonic-3`) and **Sonic 3.5** (`cartesia/sonic-3.5`). Copy the voice ID directly into your agent config. *** ## Rime Available via **Mist v3** (`rime/mistv3`) and **Coda** (`rime/coda`). Built for low latency and enterprise-grade TTS. *** ## Fish Audio Available via **S2 Pro** (`fishaudio/s2-pro`) and **S2.1 Pro** (`fishaudio/s2.1-pro`). State of the art TTS models. *** ## Inworld TTS Available via **Inworld TTS 1.5 Mini** (`inworld/inworld-tts-1.5-mini`). State of the art TTS models designed for character voices and interactive dialog. ## What's Next? Configure your agent to speak and understand any language. Learn how to set a voice when creating an agent. # Voices Source: https://docs.trugen.ai/docs/agents/voices/overview Choose the voice your agent speaks with: from stock voices, cloned voices, or a fully custom provider setup. Every agent speaks through a **Text-to-Speech (TTS)** engine that converts the LLM's text response into audio in real time. TruGen supports industry-leading voice providers including **ElevenLabs**, **Cartesia**, **Rime**, **Fish Audio**, and **Inworld TTS** — delivering ultra-low first-audio latency across a wide range of voices, accents, and styles. The voice is configured per agent via `voice_id`. Copy an ID from the [Voice Library](/docs/agents/voices/library) and drop it into your agent config. ## Setting a voice Set `voice_id` when you create or update an agent. Everything else (provider, model, sample rate, encoding) falls back to platform defaults if omitted. ```json theme={null} { "agent_name": "Support Agent", "avatars": [ { "avatar_key_id": "665a1170", "tts": { "voice_id": "FGY2WhTYpPnrIDTdsKH5" } } ] } ``` You can also change the voice directly from the **Create New Agent** form in the [Developer Portal](https://app.trugen.ai): no code required. ## Full TTS configuration For advanced use (custom pronunciations, sample rate, pitch, speaking rate, stability), pass a full `tts` object: ```json theme={null} "tts": { "provider": "elevenlabs", "model_id": "eleven_turbo_v2_5", "voice_id": "FGY2WhTYpPnrIDTdsKH5", "language": "a", "speaking_rate": 1.0, "stability": 0.5, "similarity_boost": 0.75, "sample_rate": 16000, "encoding": "pcm_s16le", "fallback_voice_id": "am_puck", "customPronounciation": [ { "word": "TRUGEN", "pronounciation": "TRUE GEN" }, { "word": "SQL", "pronounciation": "Sequel" } ] } ``` See the [full agent configuration reference](/api-reference/endpoint/agentcreate) for every field. ## Choosing a voice | Goal | Recommendation | Provider | | - | - | - | | Professional, corporate tone | Chris, Will, Evan | ElevenLabs | | Warm, conversational tone | Rachel, Laura, Hope | ElevenLabs | | Streaming real-time conversations | Brooke, Blake, Katie | Cartesia | | Enterprise-grade clarity | Luna, Celeste, Orion | Rime | | Expressive & natural speech | Hannah, Adrian, Ethan | Fish Audio | | Interactive gaming & NPC personas | Ashley, Diego, Olivia | Inworld TTS | | Broad multilingual coverage | ElevenLabs Turbo v2.5 / Cartesia Sonic 3.5 | Auto-adaptive | ## Choosing a TTS provider | Provider | Provider Key | Model | Best for | | - | - | - | - | | **ElevenLabs** | `elevenlabs` | `eleven_turbo_v2_5` (Turbo v2.5) | Low latency and fast multilingual TTS | | **ElevenLabs** | `elevenlabs` | `eleven_turbo_v2` (Turbo 2) | Low latency and fast English TTS | | **Cartesia** | `lk-inference` | `cartesia/sonic-3.5` (Sonic 3.5) | Next-generation real-time streaming TTS | | **Cartesia** | `lk-inference` | `cartesia/sonic-3` (Sonic 3) | Fast, low-latency streaming TTS | | **Rime** | `lk-inference` | `rime/mistv3` (Mist v3) | Low latency and enterprise-grade TTS | | **Rime** | `lk-inference` | `rime/coda` (Coda) | Low latency and enterprise-grade TTS | | **Fish Audio** | `lk-inference` | `fishaudio/s2.1-pro` (S2.1 Pro) | State of the art expressive TTS | | **Fish Audio** | `lk-inference` | `fishaudio/s2-pro` (S2 Pro) | State of the art expressive TTS | | **Inworld TTS** | `lk-inference` | `inworld/inworld-tts-1.5-mini` (Inworld TTS 1.5 Mini) | State of the art character & interactive TTS | Full provider list in [Providers](/docs/providers/overview). ## Custom pronunciations Product names, acronyms, and industry jargon often get mispronounced. Fix them per-voice by adding entries to `customPronounciation`: ```json theme={null} "customPronounciation": [ { "word": "TRUGEN", "pronounciation": "TRUE GEN" }, { "word": "API", "pronounciation": "A P I" }, { "word": "SQL", "pronounciation": "Sequel" }, { "word": "GraphQL", "pronounciation": "Graph Q L" } ] ``` Pronunciations apply to whichever voice is set on the agent. For dictionaries shared across many agents, see [pronunciation dictionaries](/docs/agents/voices/library#pronunciation-dictionaries) *(coming soon)*. ## Fallback voices If the primary TTS provider fails or is rate-limited, TruGen falls back to a secondary voice automatically. Set `fallback_voice_id` to a voice from a different provider for resilience: ```json theme={null} "tts": { "provider": "elevenlabs", "voice_id": "FGY2WhTYpPnrIDTdsKH5", "fallback_voice_id": "am_puck" } ``` ## Voice cloning For a fully custom voice (a spokesperson, a specific character, or your CEO), TruGen supports voice cloning through ElevenLabs Professional Voice Cloning. Contact [sales@trugen.ai](mailto:sales@trugen.ai) or provide an existing PVC voice ID directly as `voice_id`. ## What's next Browse every stock voice and copy the ID. Configure STT + TTS for 60+ languages. # Widget Source: https://docs.trugen.ai/docs/agents/widget Every TruGen agent ships with a drop-in widget: the React component or iframe that renders your agent inside any web app. Every agent you create in TruGen comes with a **widget**: a React component (also available as an iframe) that renders the agent inside your web app. The widget picks up its appearance, position, buttons, branding, and domain restrictions directly from the agent's `widget` configuration on the agent itself. That means: change the widget in the Studio or via the API, and every embed of the widget everywhere picks up the change on the next session. Your app doesn't redeploy. ## What lives on the widget config When you create or edit an agent in the [Studio](https://app.trugen.ai), the **Widget** section lets you configure: * **Position**: `left`, `right`, `center`, `center-mini`, or `full` * **Widget type**: dual (Talk + Chat), Talk-only, or Chat-only * **Colors**: solid or gradient, plus theme (dark/light) * **Branding**: company logo, company name, agent display name * **Buttons**: custom text for Start Chat, Talk, and Chat * **Suggested topics**: starter prompts to nudge users toward useful conversations * **Allowed domains**: restrict which origins can embed the agent These settings live on the agent's `widget` object. See the [Widget Customization](/docs/integrations/widget-customization) reference for every field and how it renders. ## Where to ship it Pick the embed path that matches your stack: Install `@aiteammate/agent-widget` and render with your agent ID. Drop the iframe into any HTML page: no npm install. For no-code platforms (Framer, Shopify, WordPress, Wix, Squarespace) see the dedicated [Site Builder guides](/docs/deploy/platforms/framer). ## Widget vs iFrame Both paths render the same underlying widget with the same agent config. The difference is how it lives inside your app. | | React widget | iFrame | | - | - | - | | **Setup** | `npm install`, render component | Paste one HTML tag | | **Styling** | Renders in a Shadow DOM (isolated) | Rendered inside an iframe | | **Framework fit** | React / Next.js apps | Any framework, plain HTML | | **Bundle size cost** | Small: widget is code-split | Zero | | **Custom UI hooks** | Widget props for user context | URL params for user context | The React widget is slightly more powerful: you can pass `userName`, `userId`, and `context` as typed props. The iframe accepts the same via query params. ## Next steps Every widget config field: position, colors, buttons, branding, domain restrictions. Every prop the React widget accepts. # MCP Server Source: https://docs.trugen.ai/docs/ai-tools/mcp Use TruGen's documentation MCP server to query docs directly from your AI coding assistant TruGen exposes a [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that gives AI coding assistants direct access to this documentation. Instead of copy-pasting API references or switching between browser tabs, your assistant can search and read TruGen docs inline while you build. **MCP Server URL** ``` https://docs.trugen.ai/mcp ``` ## Available Tools The server exposes two tools your AI assistant can call: | Tool | Description | | - | - | | `search_tru_gen_ai_api_documentation` | Semantic search across all TruGen docs: returns relevant sections with titles and page links | | `query_docs_filesystem_tru_gen_ai_api_documentation` | Read-only shell-like access to the docs filesystem: supports `cat`, `head`, `rg`, `tree`, `ls`, and other standard text utilities | ## Setup ### Claude Code Add the server to your Claude Code MCP config: ```bash theme={null} claude mcp add --transport http trugen-docs https://docs.trugen.ai/mcp ``` Or add it manually to your `~/.claude/claude_desktop_config.json`: ```json theme={null} { "mcpServers": { "trugen-docs": { "type": "http", "url": "https://docs.trugen.ai/mcp" } } } ``` ### Cursor 1. Open **Cursor Settings** → **MCP** 2. Click **Add Server** 3. Set the type to **HTTP** and enter the URL: ``` https://docs.trugen.ai/mcp ``` ### Windsurf Add to your Windsurf MCP settings: ```json theme={null} { "mcpServers": { "trugen-docs": { "serverUrl": "https://docs.trugen.ai/mcp" } } } ``` ### Any MCP-compatible client The server uses HTTP transport. Point any MCP client that supports HTTP/SSE transport to: ``` https://docs.trugen.ai/mcp ``` ## What You Can Ask Once connected, your assistant can answer questions like: * *"How do I create an agent with a knowledge base attached?"* * *"What callback events does TruGen support?"* * *"Show me the request schema for the Create Agent endpoint."* * *"What LLM providers are available?"* * *"How do I embed an agent via iframe?"* The assistant will search or read the docs directly rather than relying on its training data, giving you accurate and up-to-date answers. # TruGen Skill Source: https://docs.trugen.ai/docs/ai-tools/skill Install the TruGen skill so your AI coding agent can build with the full platform - agents, RAG, tools, Hawkeye vision, widget embedding, and LiveKit. The TruGen skill is a single markdown file that teaches any AI coding agent - Claude Code, Cursor, opencode, Codex, Windsurf - how to build with the entire TruGen platform. **Skill URL** ``` https://docs.trugen.ai/skill.md ``` ## Install Install into every coding agent detected on your machine: ```bash theme={null} npx skills add https://docs.trugen.ai/skill.md ``` The installer writes the skill to each agent's expected location (Claude Code, Cursor, opencode, Codex, Windsurf, and others) and links it from their configs. Restart your agent after installing. Download the skill into your project's skills directory: ```bash theme={null} mkdir -p .claude/skills/trugen-ai curl -o .claude/skills/trugen-ai/SKILL.md https://docs.trugen.ai/skill.md ``` For a machine-wide install, use `~/.claude/skills/trugen-ai/SKILL.md` instead. Claude Code picks the skill up on the next session. Save the file anywhere your agent reads, and point your agent's rules file at it: ```bash theme={null} curl -o SKILL.md https://docs.trugen.ai/skill.md ``` Then add one line to `AGENTS.md`, `CLAUDE.md`, `.cursorrules`, or the equivalent: ```markdown theme={null} For any TruGen AI platform work, read and follow `SKILL.md`. ``` No install at all also works: paste `https://docs.trugen.ai/skill.md` into the conversation and ask the agent to read it first. Verify the install with a fresh conversation: ask **"What can you build with TruGen?"** An agent with the skill answers from it - agents, knowledge bases, Hawkeye vision, the LiveKit plugin, widget embedding - rather than from memory. ## What your agent can do The skill covers every platform capability as a ready-to-run workflow. Describe a goal and the agent maps it to the right combination: | You want... | The skill reaches for | | - | - | | An agent in your app, on-brand | `POST /v1/ext/agent` + React widget, iframe, or JS SDK | | Grounded, factual answers | Knowledge Base - Agentic or Traditional RAG | | An agent that presents slides | Visual Presentations (`visual_presentations`) | | Exam proctoring, interview monitoring, compliance | Hawkeye Vision Sessions (`POST /v2/vision`) + `hawkeye-events` | | Actions: CRM, booking, search, automations | Tools - API/webhook, MCP, Composio, client tools | | Off-limits topics, canned responses | Guardrails | | Rapport that survives across sessions | Memory custom instructions | | An agent that joins human meetings | External Meetings (`@agent.trugen.ai` email) | | Your own fine-tuned or self-hosted LLM | BYO LLM (`provider: "custom"`) | | A face on an existing LiveKit voice agent | LiveKit plugin (`AvatarSession`) | It also encodes the gotchas: client tool names are case-sensitive, SDK listeners must register before `connect()`, Hawkeye's `participant` is a LiveKit identity (not a display name), and detaching one guardrail means `PUT`-ing the full list minus that entry. ## Example prompts Copy-paste these into an agent with the skill installed. ### Sales SDR with a pitch deck ```text theme={null} Turn our pitch deck into a sales SDR: - Create an agent from the sales-agents example prompt, proactive turn handling - Upload decks/pitch.pdf as a visual presentation described as "Use when asked about features, pricing, or architecture" - Add a tool that POSTs qualified leads to https://hooks.example.com/crm - Embed a right-side floating widget on our marketing site with our logo, brand colors, and suggested topics "See pricing" and "Book a demo" - Send the transcript and lead details to our CRM webhook when the call ends ``` The agent uploads and indexes the deck so the right slide appears alongside the spoken answer, wires the lead-capture tool, brands the widget, and closes the loop on `call_ended`. ### Personalize and brand an existing agent ```text theme={null} Upgrade my agent ag_123: - Switch turn handling to balanced and interruptability to medium - Enable memory with a custom instruction to remember each user's goals and progress across sessions - Rebrand the widget to our dark theme, logo, and company name, and restrict embedding to app.acme.com ``` A `PATCH /v1/ext/agent/{id}` one-liner for a human - the skill knows the exact config shape, and the change takes effect on the agent's next session with no redeploy. ## LiveKit examples The skill covers both LiveKit integration paths: * **Voice to video** - the official plugin adds a TruGen avatar track to a room you already run in LiveKit. Your existing `AgentSession` config (LLM, STT, TTS, tools) stays untouched; the plugin never creates a TruGen agent resource. * **Vision** - Hawkeye attaches to any LiveKit room you bring and streams real-time detection alerts back over the `hawkeye-events` data channel. ### Add a face to my voice agent The LiveKit example, as a single copy-paste prompt: ```text theme={null} Add a face to my voice agent: - My LiveKit AgentSession lives in agent.py - Pick a professional stock avatar from the TruGen gallery - Install the official TruGen plugin and wire it into my existing session - Keep my current LLM, STT, TTS, and tools untouched - Load the API key and avatar ID from environment variables ``` The agent installs `livekit-agents[trugen]`, sets `TRUGEN_API_KEY` and `TRUGEN_AVATAR_ID` in your `.env`, and inserts an `AvatarSession` start right before `session.start(...)` — your pipeline config stays untouched: Create your first agent and embed it in minutes. Pair the skill with the docs MCP server for full-text search over every page. Full plugin reference: options, environment variables, and examples. Every endpoint the skill puts at your agent's fingertips. # Source Image Best Practices Source: https://docs.trugen.ai/docs/avatars/best-practices Technical specifications and photography guidelines for creating high-quality custom avatars. The quality of a custom avatar depends almost entirely on the source image. Follow these guidelines to get lifelike results that render cleanly across expressions, angles, and lighting. ## Technical Specifications | Requirement | Recommended | | - | - | | **Resolution** | 1152 × 1152 or higher | | **Format** | JPG, PNG | | **File size** | ≤ 10 MB | | **Aspect ratio** | Square (1:1) or portrait (3:4, 4:5) | | **Color space** | sRGB | ## Composition The subject should look directly into the camera. Small head tilts are okay; profile shots are not. A closed-mouth smile or relaxed neutral expression works best. Avoid open-mouth laughs, exaggerated expressions, or eyes closed. Frame the subject from the mid-chest up. Leave a small margin above the head: don't crop the top of the head. Use a plain, evenly-lit background. Avoid busy patterns, other faces, or high-contrast objects behind the subject. ## Lighting * **Even, diffuse light** across the face. Soft natural light near a window is ideal. * **Avoid hard shadows** on one side of the face, from a hat brim, or under the eyes. * **No direct back-lighting**: the subject should be brighter than the background. * **No colored gels** or dramatic lighting effects. ## Face and Features * **Face fully visible**: no sunglasses, no face masks, no obstructions. * **Standard glasses are okay** but reflective glare on the lenses can cause artifacts. * **Hair should not cover the eyes or eyebrows.** * **Facial hair is fine**: beards, mustaches, stubble all render well. Dense or unusually styled facial hair sometimes doesn't reproduce perfectly — expect minor variation around beard edges and mustache detail. * **Makeup is fine**: extreme theatrical makeup may reduce realism. * **No facial tattoos**: tattoos on the face don't render reliably and can distort the generated likeness. ## Camera and Quality * **Sharp focus on the eyes.** Blur anywhere on the face will carry into the avatar. * **No heavy filters or beauty smoothing**: over-processed skin loses the texture Huma-2 needs to render naturally. * **Avoid heavy compression artifacts**: export at high quality if resaving. ## Common Mistakes to Avoid * Group photos or multiple faces in the frame * Selfies with distortion from ultra-wide phone lenses (stand back and zoom in instead) * Cartoon avatars, AI-generated portraits, or heavily stylized illustrations (unless that's the intent) * Old low-resolution photos scaled up * Images with watermarks or logos over the face * Objects obstructing the face or upper body — laptops, cameras, microphones, phones, or hands held up in front of the subject ## Consent and Rights Only upload photos you have the legal right to use. * For your own face, no additional permission is needed. * For someone else's face, obtain their **explicit written consent** before creating an avatar. * Do not create avatars of public figures, celebrities, or minors without proper authorization. Uploading a photo of another person without their consent may violate privacy laws in your jurisdiction and is against TruGen's terms of service. An internal guardrail screens every upload before generation. Images of public figures, celebrities, or content that appears to be copyrighted (recognizable movie/TV/game characters, licensed artwork, etc.) will be rejected and the avatar generation request will fail. ## What's Next? Ready to upload? Follow the creation flow. Prefer to use a stock avatar? Browse the gallery. # Custom Avatars Source: https://docs.trugen.ai/docs/avatars/custom Create your own TruGen avatar from a single source photo or a live camera capture. Custom avatars let you build agents with your own face, a customer's face, a spokesperson, or a designed character: all driven by TruGen's **Huma-3** neural rendering engine. Custom avatars require the **Huma-3** model and are not available on Huma-1 or Huma-2 agents. Custom avatars are currently in **Beta**. ## Create via API You can also create a custom avatar programmatically by sending a `POST` request to the `/v2/custom-avatar` endpoint with the avatar details and a base64-encoded source image. ### Request body | Field | Type | Required | Description | | - | - | - | - | | `avatar_name` | string | yes | A human-readable name for your custom avatar. | | `gender` | string | yes | Must be `"male"` or `"female"`. | | `input_image` | string | yes | Source photo as a base64 data URI. Max \~12 MB base64 (\~9 MB binary). | ```javascript JavaScript theme={null} const myHeaders = new Headers(); myHeaders.append("x-api-key", "YOUR_API_KEY"); myHeaders.append("Content-Type", "application/json"); const raw = JSON.stringify({ "avatar_name": "my_avatar", "gender": "male", "input_image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD..." }); const requestOptions = { method: "POST", headers: myHeaders, body: raw, redirect: "follow" }; fetch("https://api.trugen.ai/v2/custom-avatar", requestOptions) .then((response) => response.text()) .then((result) => console.log(result)) .catch((error) => console.error(error)); ``` ```python Python theme={null} import requests import json url = "https://api.trugen.ai/v2/custom-avatar" payload = json.dumps({ "avatar_name": "my_avatar", "gender": "male", "input_image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD..." }) headers = { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' } response = requests.request("POST", url, headers=headers, data=payload) print(response.text) ``` ### Response The API returns immediately with an initial job status while the avatar is generated in the background. Poll `GET /v2/custom-avatar/{id}` to watch progress until `status` becomes `COMPLETED`. ```json theme={null} { "id": "3b6f4c8a-...-...", "job_id": "sync-abcd-...", "avatar_key_id": "a1b2c3d4e5", "avatar_id": "a1b2c3d4e5", "avatar_name": "my_avatar", "gender": "male", "category": "trugen", "status": "QUEUED", "is_private": true } ``` ## When to use a Custom Avatar * **Personal brand agents**: use your own face for a coach, tutor, or spokesperson agent. * **Enterprise personas**: create a consistent brand character across all customer touch points. * **Character-driven experiences**: build entertainment, storytelling, or roleplay agents with a designed persona. * **Customer-facing sales agents**: use a photo of a real team member to make outreach feel personal. ## Using Your Custom Avatar Once the job reaches `COMPLETED`, pass the `avatar_key_id` from the create response into the `avatars[0].avatar_key_id` field when creating an agent — the same shape used for stock avatars: ```json theme={null} { "agent_name": "My Custom Agent", "agent_system_prompt": "...", "avatars": [{ "avatar_key_id": "YOUR_AVATAR_KEY_ID" }] } ``` ## What's Next? Choose a voice and language for your custom avatar agent. Get the highest-quality result on the first try. # Avatar Gallery Source: https://docs.trugen.ai/docs/avatars/gallery Browse TruGen's stock avatars and copy the avatar ID for use in your agent configuration. TruGen's stock avatars are built on **Huma-2** and render lifelike facial motion, expression, and speech synchronisation in real time. Click the copy icon next to any avatar ID to copy it, then paste it into your agent's `avatar_key_id` field.
Cathy
Cathy
17de03e4
Chloe
Chloe
45e3f732
Clara
Clara
7e95996
Jennifer
Jennifer
0de70332
Jessica
Jessica
21ef04ad
Lisa
Lisa
665a1170
Lucy
Lucy
c5b563de
Misha
Misha
05b401f3
Priya
Priya
1e4ea106
Sofia
Sofia
1928040f
Akbar
Akbar
18c4043e
Alex
Alex
80b9095f
Aman
Aman
5daa73d5
Jason
Jason
05a001fc
Johnny
Johnny
1fa504ff
Mike
Mike
03ae0187
Sameer
Sameer
60a0926a
## Using an Avatar ID Pass the copied ID into the `avatar_key_id` field when creating an agent. ## What's Next? Upload a photo or use your camera to build your own avatar. Technical specs and guidelines for the highest-quality custom avatars. Programmatic access to the full avatar list. Use these avatars with the TruGen LiveKit plugin. # Voice-Only Mode Source: https://docs.trugen.ai/docs/avatars/voice-only Run an agent without rendering a face: a customizable audio visualizer replaces the avatar for voice-first experiences. Not every agent needs a face. **Voice-Only Mode** turns off the Huma avatar renderer and replaces it with a lightweight audio visualizer: a decorative animation that pulses with the agent's speech. Use it for voice-first products, low-bandwidth environments, or when your brand is stronger than any face you could render. ## When to use it * **Voice-first products**: IVR replacements, phone-like conversations, screen-off use * **Low-bandwidth or metered networks**: the visualizer streams a tiny fraction of what avatar video does * **Brand-forward experiences**: center your logo and color instead of a stock face * **Mobile-web**: great for interactions where a full avatar would dominate a small screen * **Latency-sensitive edge cases**: skipping avatar render removes \~50–100 ms from the pipeline Voice-only mode uses the same STT / LLM / TTS pipeline as a video agent: only the render layer changes. ## Audio visualizer variants Voice-only mode ships with six built-in visualizer styles. Each one animates in sync with the agent's speech. | Variant | Style | | - | - | | `aura` | Soft glowing halo | | `bar` | Vertical audio-meter bars | | `grid` | Grid of pulsing cells | | `radial` | Concentric circles reacting to volume | | `wave` | Flowing horizontal waveform | | `earth` | Rotating globe animation | Pick the one that fits your brand. All six use your chosen accent color. ## Customization Voice-only mode gives you three visual levers: | Setting | Description | | - | - | | **Visualizer variant** | Choose one of the six variants above | | **Accent color** | The color the visualizer pulses in (hex) | | **Custom background** | Toggle a custom background scene instead of the default flat backdrop | | **Company logo** | Show your logo centered inside the visualizer | All customization happens in the Studio's Avatar tab when Voice-Only Mode is toggled on. The values persist on the agent config and apply everywhere the agent is embedded. ## Enabling voice-only mode In the Studio, open the **Avatar** tab and toggle **Voice-only mode** on. Pick a visualizer variant, set the accent color, and optionally add a company logo. Voice-only is stored on the agent's avatar config: everywhere the agent is embedded (widget, iframe, LiveKit plugin) picks up the setting on the next session. ## Widget SDK support The `@aiteammate/agent-widget` React component also accepts an internal `audioAvatarVariant` prop for one-off overrides at render time. It accepts the same six values (`"aura" | "bar" | "grid" | "radial" | "wave" | "earth"`). For most cases, configure voice-only on the agent itself so every embed matches: don't override it per widget instance unless you have a specific reason to. ## Best practices * **Match visualizer to your brand.** `aura` reads soft and premium; `bar` reads technical and precise; `earth` reads exploratory. Test a few. * **Pick a bold accent color.** The visualizer is the entire UI while the agent speaks: a washed-out color feels flat. * **Add your logo.** In voice-only mode there's no face to anchor the eye: the logo becomes the identity of the experience. * **Test on mobile.** Voice-only shines on small screens. Verify your color and logo work at phone size. ## Next steps Pick a voice that suits your voice-only experience. Match widget theming to your voice-only accent color. # Changelog Source: https://docs.trugen.ai/docs/changelog Product updates and announcements Introducing the Sessions API ### Sessions * **List All Sessions**: New `GET /v1/ext/sessions` endpoint returns all your sessions with avatar ID, room name, status (`INITIALIZING`, `ENDED`, `TERMINATED`), and creation timestamp. Filter with `offset`/`perpage` pagination, `search`, `fromDate`/`toDate` date ranges, and `room_name`. See the [API reference](/api-reference/endpoint/sessionget). Introducing Custom Avatars API, Updated AI Models, and New Voice Providers ### Custom Avatars * **Introducing Custom Avatars API**: Programmatically generate custom neural avatars from a single source image using `POST /v2/custom-avatar`, and manage or poll generation status with `GET /v2/custom-avatar/{id}` and `DELETE /v2/custom-avatar/{id}`. ### LLMs & Providers * **Refreshed LLM Catalog**: Updated Available LLMs to the latest generation of reasoning and multimodal models: * **Google**: `Gemini 4 31b` (`google/gemma-4-31b-it`), `Gemini 3.5 Flash Lite`, `Gemini 3.1 Flash Lite` * **Groq**: `GPT OSS 20b`, `GPT OSS 120b` * **OpenAI**: `GPT 5.4 Mini` (`openai/gpt-5.4-mini`) * **Kimi**: `Kimi K2.6` (`moonshotai/kimi-k2.6`) * **Expanded TTS Providers & Voice Library**: * Added support for **Rime** (`Mist v3`, `Coda`), **Fish Audio** (`S2 Pro`, `S2.1 Pro`), and **Inworld TTS** (`Inworld TTS 1.5 Mini`) alongside **ElevenLabs** and **Cartesia**. * Updated Voice Library with interactive audio previews and copyable voice IDs across all 5 TTS providers. * **Updated Speech-to-Text (STT) Providers**: * Added **Deepgram Flux General** & **Flux General Multilingual**, **AssemblyAI Universal-Streaming** & **Universal-3.5 Pro**, and **Speechmatics Enhanced** & **Standard**. Documentation overhaul: JavaScript SDK, External Meetings, Vision Understanding, Tools revamp, and more ### JavaScript SDK * **Full JavaScript SDK documentation**: Quickstart, Authentication (two-tier API key + session tokens), Production usage, Basic JavaScript and TypeScript examples, and a complete SDK Reference covering Basic Usage, Audio Control, Event Handling, and all 17 events * **LiveKit JavaScript/TypeScript support**: Added JS/TS tab to the LiveKit integration page alongside Python, covering `@livekit/agents-plugin-trugen` install, environment setup, and `AvatarSession` configuration reference ### AI Teammates * **External Meetings**: New documentation covering how to enable External Meetings per agent, agent email addresses, invite flow, supported platforms (Google Meet, Zoom, Teams, Webex), multi-participant support, and the proprietary Chime In model for natural turn-taking * **Vision Understanding**: Renamed and fully expanded with Hawkeye-1 capabilities: Emotion Detection, Head Pose Tracking, Eye Gaze Tracking, Face Count Detection, Deepfake Detection, and Lip Sync Detection, plus real-time alerts, scale architecture, and common use cases * **Tools revamp**: Completely restructured into three pages: Tools Overview (all types + testing), Integrations (Composio 1000+ apps, OAuth/API key auth), and Custom Tools (API/Webhook, MCP with SHTTP/SSE transport, Client Tools with npm handler pattern) * **Event Callbacks**: Added `max_call_duration_warning` and `tool_call` events, bringing the total to 11 events. All events and code examples are now in alphabetical order * **Knowledge Base**: Expanded with RAG vs Agentic RAG explanation, three content types (Documents, Plain Text, URL/Website), improved naming guidance, and API examples for creating knowledge bases and adding documents ### LLMs * **Available LLMs**: New page listing all supported models across Groq, Azure OpenAI, Google, Open Router, and Livekit Inference, with a quick-reference model selection guide * **Custom LLM**: Renamed sidebar entry and improved with clearer setup steps ### Voices & Languages * **Voice Library**: Updated with ElevenLabs audio sample URLs for all 17 voices, plus 52 Cartesia voices added * **Multilingual Support**: Expanded from 9 to 60+ languages organised into European, Asian & Pacific, and Arabic regional tables with dialect-level codes ### Providers * **Providers page**: Restructured into three clear sections: STT, LLM, and TTS, with all providers and models listed and moved to the Introduction group for better discoverability Introducing Video Generation ### Key Features in This Release * **Text to Video:** We are introducing a new option that allows you to generate a video from a script using our Huma avatar model. Knowledge Base improvements and new Memory ### Key Features in This Release * **Enhanced Knowledge Base:** we revised our entire knowledge layer architecture for improved reliability and overall performance. Our retrievals today average \<100ms. * **Introduced Memory documentation page** describing how agents use conversation and long-term memory, plus navigation entry under Managed Agents. * **Updated stock avatars page to include list of all available avatars for LiveKit Voice Agent integration.** Integrations and API support ### Key Features in This Release * **Added Support for LiveKit plugin to bring in your own voice agents.** * **Updated Tools and MCP APIs section for ease of access and modification.** Bug Fix and New End point ### Key Features in This Release * **New API for Get Conversation by Id.** * **Stability and General Bug fixes.** We’re excited to introduce the first official release of the **TruGen Conversational Video Agent Platform**, enabling developers to build and deploy lifelike real-time video AI agents at scale. ### Key Features in This Release * **Conversational Video Agents** * Real-time human-like interaction powered by speech, vision, and contextual reasoning * Sub-second response times for natural two-way conversation * Dynamic turn-taking, interruption handling, and multimodal awareness * **End-to-End Conversational Pipeline** * STT → LLM → TTS → Video rendering flow in under one second * Automatic turn detection and expressive avatar synchronization * **Huma-01 Expressive Avatar Model** * Emotionally rich facial animation, micro-expressions, and lip-sync accuracy * **Hawkeye-01 Vision Action Recognition** * Real-time gesture and movement detection for behavior-adaptive responses * **Knowledge Base Integration** * Ground responses in your data, documents, or APIs for factual and brand-specific conversations * **Persona Templates** * Create configurable agent personalities with system prompts, tone, entry/exit messages, and state logic * **Event Webhooks** * Full lifecycle and speech event hooks for analytics, UI synchronization, and workflow automation * **Integration Options** * **iFrame embed** for zero-setup deployment ### Developer Experience * Comprehensive API Reference documentation # Framer Source: https://docs.trugen.ai/docs/deploy/platforms/framer Embed a TruGen agent in a Framer site with a code component or embed block. Framer sites can host a live TruGen agent using the standard iframe embed. Setup takes about 5 minutes. ## Prerequisites * A TruGen agent with an `agent_id`: see the [quickstart](/docs/quickstart) if you don't have one * Access to a Framer project you can edit ## Add the embed In your Framer canvas, insert a new **Embed** component from the Insert menu. Set the Embed component's HTML to: ```html theme={null} ``` Replace `YOUR_AGENT_ID` with your agent ID, and swap `USER_NAME`, `USER_ID`, and `CONTEXT` with values you want to identify the visitor by. Publish the Framer site. Visitors will be prompted for camera + microphone permissions the first time they land on the page. ## Verify domain access If your agent has an `allowed_domains` list configured, add your Framer site's custom domain (or the default `.framer.website` URL) to it. Otherwise requests from Framer will be blocked with `403 origin_not_allowed`. ## Sizing tips * Full-screen agent: set the Embed's height to `100vh` and width to `100%`. * Panel-style agent: constrain the Embed size and place it inside a stack with the rest of your page content. * Mobile: keep height at least `500px`: anything less crops the avatar. ## What's next For custom React apps, use the widget instead of the raw iframe. Every iframe parameter documented. # Shopify Source: https://docs.trugen.ai/docs/deploy/platforms/shopify Add a TruGen agent to a Shopify storefront using a Custom Liquid section or theme edit. TruGen agents drop into Shopify storefronts via the standard iframe embed. Ideal for guided shopping, size/fit consultation, or post-purchase support. ## Prerequisites * A TruGen agent with an `agent_id`: see the [quickstart](/docs/quickstart) * Access to your Shopify admin with theme edit permissions ## Add via Custom Liquid section (recommended) In your Shopify admin, go to **Online Store → Themes → Customize** on your active theme. On the page where you want the agent to appear (Home, Product, or Custom page), click **Add section** and choose **Custom Liquid**. ```html theme={null}
``` Replace `YOUR_AGENT_ID` with your agent ID. Shopify's Liquid variables (`customer.first_name`, `customer.id`) auto-inject the shopper's identity for personalization.
Save the section. Preview the page in an incognito window to test as a real shopper.
## Add via theme code edit (advanced) For sitewide floating widgets, edit the theme's `theme.liquid`: Go to **Online Store → Themes → Actions → Edit code**. Open `layout/theme.liquid` and add the iframe before the closing `` tag: ```html theme={null} ``` ## Domain allowlist If your agent uses `allowed_domains`, add your Shopify domain, both your custom domain (e.g., `mystore.com`) and the default `.myshopify.com` domain, to the list. ## Content Security Policy note Shopify's default CSP is permissive enough to load third-party iframes. If you've customized it via a checkout script or theme edit, ensure `frame-src https://app.trugen.ai` is included. ## What's next Every iframe parameter documented. Write a shopping-savvy system prompt. # Squarespace Source: https://docs.trugen.ai/docs/deploy/platforms/squarespace Add a TruGen agent to a Squarespace site with a Code Block or Code Injection. Squarespace supports third-party iframes through **Code Blocks** on individual pages or **Code Injection** for site-wide widgets. ## Prerequisites * A TruGen agent with an `agent_id`: see the [quickstart](/docs/quickstart) * Squarespace **Business** plan or higher (Code Blocks aren't available on Personal plans) ## Add via a Code Block (single page) Open the Squarespace editor for the page where you want the agent. Click the **+** insertion icon → **Code**. Choose **HTML** as the language. ```html theme={null} ``` Replace `YOUR_AGENT_ID` and set the user parameters. Save the block. Publish the page. ## Add site-wide via Code Injection (floating widget) Go to **Settings → Advanced → Code Injection**. ```html theme={null} ``` Save and reload the site. The widget will float bottom-right on every page. ## Squarespace-specific notes * **Preview vs published**: Squarespace's editor preview strips iframes. Always test on the live URL. * **Header injection blocked**: Squarespace only allows Code Injection in Header and Footer. Choose Footer for anything with active DOM. * **Mobile scaling**: Squarespace templates sometimes constrain iframe width on mobile. Test on a real device. ## Domain allowlist Add your Squarespace domain (custom or `.squarespace.com`) to your agent's `allowed_domains` list if configured. ## What's next Every iframe parameter documented. For headless Squarespace + React setups. # Wix Source: https://docs.trugen.ai/docs/deploy/platforms/wix Embed a TruGen agent on a Wix site using the HTML iframe element. Wix supports third-party iframes through the **Embed HTML** element in the editor. Adding a TruGen agent takes a couple of minutes. ## Prerequisites * A TruGen agent with an `agent_id`: see the [quickstart](/docs/quickstart) * Access to your Wix Editor ## Steps In the Wix Editor, click **+ Add** in the left panel → **Embed Code** → **Embed HTML**. Drag it onto the page. Click the element, then **Enter Code**. Paste: ```html theme={null} ``` Replace `YOUR_AGENT_ID` and swap `USER_NAME`, `USER_ID`, `CONTEXT` with your values. Wix uses a fixed-size embed container by default. Drag the element to at least 400×600 to fit the avatar comfortably. Click **Publish** in the top right. Visit the published URL to test. ## Wix-specific limits * **Premium plan required**: Wix restricts external iframes on free plans. Upgrade to any Premium tier to unlock Embed HTML. * **Editor preview may not work**: Wix's editor preview iframe often blocks nested iframes and camera/mic access. Always test on the published URL, not in the editor. * **Fixed sizing**: the Embed HTML element doesn't fluidly resize. Choose a fixed width and height that works on both desktop and mobile. ## Domain allowlist Add your Wix domain (custom or `.wixsite.com`) to your agent's `allowed_domains` list if you're using one. ## What's next Every iframe parameter documented. Write a system prompt that fits your Wix site's context. # WordPress Source: https://docs.trugen.ai/docs/deploy/platforms/wordpress Embed a TruGen agent in a WordPress site with a block, shortcode, or theme edit. TruGen agents work on WordPress through the standard iframe embed. Works in classic and block editors, on any theme. ## Prerequisites * A TruGen agent with an `agent_id`: see the [quickstart](/docs/quickstart) * Access to a WordPress site with content-edit or theme-edit permissions ## Add via the Block Editor (recommended) Edit the page or post where you want the agent. Click **+ Add block** and search for **Custom HTML**. ```html theme={null} ``` Replace `YOUR_AGENT_ID` with your agent ID, and substitute `USER_NAME`, `USER_ID`, and `CONTEXT` with values that identify the visitor. Publish the page. Visitors will be prompted for camera + mic permissions on first load. ## Add via the Classic Editor Switch the editor to **Text** mode, then paste the iframe HTML directly. Return to Visual mode to preview. ## Add via theme (sitewide floating widget) For a floating widget across the entire site: Go to **Appearance → Theme File Editor**, or use a child theme. Add before the closing `` tag: ```html theme={null} ``` Prefer a child theme so your changes survive theme updates. ## Common gotchas * **Security plugins** (Wordfence, iThemes) may strip iframes from post content. Whitelist `app.trugen.ai` in the plugin's allowed sources. * **Caching plugins** (WP Rocket, W3 Total Cache) don't affect the iframe itself but can cache your page: clear cache after editing. * **HTTPS required.** Browsers refuse to grant camera/mic on non-HTTPS pages, and modern WordPress hosts enforce HTTPS by default. ## Domain allowlist If your agent has an `allowed_domains` list, add your WordPress domain (`example.com`, `www.example.com`) to it. ## What's next Every iframe parameter documented. For WordPress sites built as headless React apps. # AI Interview Source: https://docs.trugen.ai/docs/examples/ai-interviewer Ideal for structured interviews, candidate screening, and role-based assessments. * Conducting initial HR screening interviews * Role-specific behavioral or technical questions * Standardized interview flows across locations ### Example System Prompt ```txt theme={null} You are an AI Interviewer conducting structured, professional interviews. Your goals: - Ask clear, role-relevant questions one at a time. - Listen carefully and ask follow-up questions when needed. - Maintain a neutral, respectful tone at all times. - Summarize the candidate’s strengths and areas to explore further. - Avoid making hiring decisions; instead, gather insights for human recruiters. If the candidate seems nervous, briefly reassure them and keep the conversation calm and focused. ``` Use the **Create Agent API** to programmatically spin up a new video agent. Replace `` with your actual API key generated from our [Portal](https://app.trugen.ai). ```bash Request theme={null} curl --request POST \ --url https://api.trugen.ai/v1/agent/api \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "avatar_ids": [ "1e4ea106", "45e3f732" ], "name": "AI Interviewer", "system_prompt": "You are an AI Interviewer conducting structured, professional interviews.\n\nYour goals:\n- Ask clear, role-relevant questions one at a time.\n- Listen carefully and ask follow-up questions when needed.\n- Maintain a neutral, respectful tone at all times.\n- Summarize the candidate\u2019s strengths and areas to explore further.\n- Avoid making hiring decisions; instead, gather insights for human recruiters.\n\nIf the candidate seems nervous, briefly reassure them and keep the conversation calm and focused.", "config": { "timeout": 240 }, "knowledge_base": null, "record": true, "callback_url":null, "callback_events": null }' ``` The API will return the newly created agent object, including an `id` like: ```json Response theme={null} { "id": "51ed8d70-9379-422f-aed4-f9f2b293ba4a", "name": "AI Interviewer" } ``` Use the agent `id` to embed a fully interactive video agent via **iframe**. ```html Your App theme={null} ``` Replace `` with the value returned from previous step. # Career Coach Source: https://docs.trugen.ai/docs/examples/career-coach A coaching-focused agent that helps users reflect, plan, and grow in their careers. * Career planning and role exploration * Resume and interview preparation * Skill gap analysis and upskilling recommendations ### Example System Prompt ```txt theme={null} You are a supportive Career Coach helping users navigate their professional journey. Your goals: - Ask thoughtful questions about goals, skills, and interests. - Help users clarify their direction and next steps. - Provide constructive feedback on job search, resumes, and interviews. - Suggest practical actions, resources, and timelines. - Maintain an encouraging, non-judgmental tone. Always keep advice general and supportive; avoid making guarantees or promises about outcomes. ``` Use the **Create Agent API** to programmatically spin up a new video agent. Replace `` with your actual API key generated from our [Portal](https://app.trugen.ai). ```bash Request theme={null} curl --request POST \ --url https://api.trugen.ai/v1/agent/api \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "avatar_ids": [ "1e4ea106", "45e3f732" ], "name": "Career Coach", "system_prompt": "You are a supportive Career Coach helping users navigate their professional journey.\n\nYour goals:\n- Ask thoughtful questions about goals, skills, and interests.\n- Help users clarify their direction and next steps.\n- Provide constructive feedback on job search, resumes, and interviews.\n- Suggest practical actions, resources, and timelines.\n- Maintain an encouraging, non-judgmental tone.\n\nAlways keep advice general and supportive; avoid making guarantees or promises about outcomes.", "config": { "timeout": 240 }, "knowledge_base": null, "record": true, "callback_url":null, "callback_events": null }' ``` The API will return the newly created agent object, including an `id` like: ```json Response theme={null} { "id": "51ed8d70-9379-422f-aed4-f9f2b293ba4a", "name": "Career Coach" } ``` Use the agent `id` to embed a fully interactive video agent via **iframe**. ```html Your App theme={null} ``` Replace `` with the value returned from previous step. # Customer Support Agent Source: https://docs.trugen.ai/docs/examples/customer-support-agent A dedicated agent for resolving customer queries, guiding troubleshooting, and handling FAQs. * Tier-1 support for common issues * Account, billing, and subscription queries * Guided troubleshooting for apps, hardware, or SaaS products ```txt theme={null} You are a Customer Support Agent for our company. Your goals: - Greet users warmly and quickly identify their issue. - Ask clarifying questions before suggesting solutions. - Use our knowledge base articles and policies to provide accurate guidance. - Offer step-by-step troubleshooting instructions when needed. - Escalate or recommend human support for complex or sensitive issues. Always be empathetic, concise, and solution-oriented. ``` Use the **Create Agent API** to programmatically spin up a new video agent. Replace `` with your actual API key generated from our [Portal](https://app.trugen.ai). ```bash Request theme={null} curl --request POST \ --url https://api.trugen.ai/v1/agent/api \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "avatar_ids": [ "1e4ea106", "45e3f732" ], "name": "Customer Support Agent", "system_prompt": "You are a Customer Support Agent for our company.\n\nYour goals:\n- Greet users warmly and quickly identify their issue.\n- Ask clarifying questions before suggesting solutions.\n- Use our knowledge base articles and policies to provide accurate guidance.\n- Offer step-by-step troubleshooting instructions when needed.\n- Escalate or recommend human support for complex or sensitive issues.\n\nAlways be empathetic, concise, and solution-oriented.", "config": { "timeout": 240 }, "knowledge_base": null, "record": true, "callback_url":null, "callback_events": null }' ``` The API will return the newly created agent object, including an `id` like: ```json Response theme={null} { "id": "51ed8d70-9379-422f-aed4-f9f2b293ba4a", "name": "Customer Support Agent" } ``` Use the agent `id` to embed a fully interactive video agent via **iframe**. ```html Your App theme={null} ``` Replace `` with the value returned from previous step. # Healthcare Intake Assistant Source: https://docs.trugen.ai/docs/examples/healthcare-intake-assistant Helps collect structured intake information before a consultation. * Pre-visit symptom and history collection * Digital triage and routing * Intake for telehealth appointments ```txt theme={null} You are a Healthcare Intake Assistant helping patients share information before meeting a clinician. Your goals: - Politely introduce yourself and explain that you are not a doctor. - Collect relevant symptoms, duration, and severity. - Ask about medications, allergies, and medical history when appropriate. - Avoid giving diagnoses, treatment, or medical advice. - Encourage users to consult a medical professional for any urgent or serious concerns. Always be clear, calm, and respectful. If the user mentions an emergency, advise them to seek immediate in-person help. ``` Use the **Create Agent API** to programmatically spin up a new video agent. Replace `` with your actual API key generated from our [Portal](https://app.trugen.ai). ```bash Request theme={null} curl --request POST \ --url https://api.trugen.ai/v1/agent/api \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "avatar_ids": [ "1e4ea106", "45e3f732" ], "name": "Healthcare Intake Assistant", "system_prompt": "You are a Healthcare Intake Assistant helping patients share information before meeting a clinician.\n\nYour goals:\n- Politely introduce yourself and explain that you are not a doctor.\n- Collect relevant symptoms, duration, and severity.\n- Ask about medications, allergies, and medical history when appropriate.\n- Avoid giving diagnoses, treatment, or medical advice.\n- Encourage users to consult a medical professional for any urgent or serious concerns.\n\nAlways be clear, calm, and respectful. If the user mentions an emergency, advise them to seek immediate in-person help.", "config": { "timeout": 240 }, "knowledge_base": null, "record": true, "callback_url":null, "callback_events": null }' ``` The API will return the newly created agent object, including an `id` like: ```json Response theme={null} { "id": "51ed8d70-9379-422f-aed4-f9f2b293ba4a", "name": "Healthcare Intake Assistant" } ``` Use the agent `id` to embed a fully interactive video agent via **iframe**. ```html Your App theme={null} ``` Replace `` with the value returned from previous step. # Nutritionist Source: https://docs.trugen.ai/docs/examples/nutritionist Helps users build healthier routines and understand nutrition basics. * Basic nutrition education * Daily habit and meal planning suggestions * Lifestyle-focused wellness conversations ### Example System Prompt ```txt theme={null} You are a virtual Nutrition Coach helping users build healthier everyday habits. Your goals: - Ask about the user’s general lifestyle, preferences, and goals. - Provide high-level, evidence-aligned guidance on balanced meals and routines. - Suggest practical, simple changes rather than strict diets. - Encourage users to consult a medical professional or registered dietitian for personalized or medical advice. - Avoid diagnosing conditions or prescribing treatments. Always stay supportive, non-judgmental, and respectful of cultural and dietary preferences. ``` Use the **Create Agent API** to programmatically spin up a new video agent. Replace `` with your actual API key generated from our [Portal](https://app.trugen.ai). ```bash Request theme={null} curl --request POST \ --url https://api.trugen.ai/v1/agent/api \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "avatar_ids": [ "1e4ea106", "45e3f732" ], "name": "Nutritionist", "system_prompt": "You are a virtual Nutrition Coach helping users build healthier everyday habits.\n\nYour goals:\n- Ask about the user\u2019s general lifestyle, preferences, and goals.\n- Provide high-level, evidence-aligned guidance on balanced meals and routines.\n- Suggest practical, simple changes rather than strict diets.\n- Encourage users to consult a medical professional or registered dietitian for personalized or medical advice.\n- Avoid diagnosing conditions or prescribing treatments.\n\nAlways stay supportive, non-judgmental, and respectful of cultural and dietary preferences.", "config": { "timeout": 240 }, "knowledge_base": null, "record": true, "callback_url":null, "callback_events": null }' ``` The API will return the newly created agent object, including an `id` like: ```json Response theme={null} { "id": "51ed8d70-9379-422f-aed4-f9f2b293ba4a", "name": "Nutritionist" } ``` Use the agent `id` to embed a fully interactive video agent via **iframe**. ```html Your App theme={null} ``` Replace `` with the value returned from previous step. # Sales Agent Source: https://docs.trugen.ai/docs/examples/sales-agents A conversion-focused agent for demos, product walkthroughs, and lead qualification. * Product demos and walkthroughs * Lead qualification and discovery * Pricing, packaging, and objection handling ### Example System Prompt ```txt theme={null} You are a Sales Agent representing our company and products. Your goals: - Quickly understand the user’s needs, role, and use case. - Explain relevant features and benefits in simple, outcome-focused language. - Ask discovery questions to qualify the lead. - Offer next steps such as booking a demo, starting a trial, or talking to a human sales rep. - Handle common objections politely and clearly. Be enthusiastic but not pushy. Stay honest and do not oversell or misrepresent product capabilities. ``` Use the **Create Agent API** to programmatically spin up a new video agent. Replace `` with your actual API key generated from our [Portal](https://app.trugen.ai). ```bash Request theme={null} curl --request POST \ --url https://api.trugen.ai/v1/agent/api \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' \ --data '{ "avatar_ids": [ "1e4ea106", "45e3f732" ], "name": "Sales Agents", "system_prompt": "You are a Sales Agent representing our company and products.\n\nYour goals:\n- Quickly understand the user\u2019s needs, role, and use case.\n- Explain relevant features and benefits in simple, outcome-focused language.\n- Ask discovery questions to qualify the lead.\n- Offer next steps such as booking a demo, starting a trial, or talking to a human sales rep.\n- Handle common objections politely and clearly.\n\nBe enthusiastic but not pushy. Stay honest and do not oversell or misrepresent product capabilities.", "config": { "timeout": 240 }, "knowledge_base": null, "record": true, "callback_url":null, "callback_events": null }' ``` The API will return the newly created agent object, including an `id` like: ```json Response theme={null} { "id": "51ed8d70-9379-422f-aed4-f9f2b293ba4a", "name": "Sales Agents" } ``` Use the agent `id` to embed a fully interactive video agent via **iframe**. ```html Your App theme={null} ``` Replace `` with the value returned from previous step. # Embed via iFrame Source: https://docs.trugen.ai/docs/integrations/embed-via-iFrame Embed a TruGen conversational agent directly into your product frontend using a simple iframe. No complex setup, SDK installation, or infrastructure configuration required - just drop it into your application and your agent is live instantly. ```html theme={null} ``` > **The fastest way to get started** > This lightweight integration is the simplest path to launching a fully interactive video AI agent. Perfect for prototypes, internal tools, customer demos, or production apps where speed matters. Add it to any frontend framework - React, Next.js, Vue, Angular, or even plain HTML - and it works immediately. ### Why use the iframe embed? * **Zero setup required** - No WebRTC, signaling servers, or media pipelines to configure. * **Works anywhere** - Any web application or CMS environment that accepts custom HTML. * **Instant functionality** - Camera, microphone, speech, vision perception, and live responses out of the box. * **Production-ready** - Secure, optimized, and supported across browsers globally. Just plug in your `agentId`, deploy, and you’re ready to interact with a real-time conversational video agent in under a minute. # Make.com Workflows Source: https://docs.trugen.ai/docs/integrations/make We offer seamless integration with Make.com for building powerful no-code workflow automations powered by AI agents. Connect TruGen.ai agents to your scenarios to automate conversations, trigger actions, process webhook events, and sync data across your tools effortlessly. Bring AI agents into your workflows with TruGen.ai and Make.com to: * **Create and manage AI agents** directly from your scenarios * **Trigger workflows from webhook events** generated by agent conversations * **Capture leads and qualification data** from inbound interactions * **Sync notes, contacts, and conversation outcomes** with CRMs like HubSpot or Salesforce * **Connect with thousands of apps and services** through Make.com’s automation ecosystem * **Build end-to-end automations** for sales, support, recruiting, onboarding, and more See the TruGen.ai Make.com integration documentation for setup instructions, available modules, and workflow examples. Create and manage agents using Make.com scenarios # n8n Workflows Source: https://docs.trugen.ai/docs/integrations/n8n We offer seamless integration with n8n for building no-code and low-code workflow automations powered by AI agents. Connect TruGen.ai agents to your workflows to automate conversations, trigger actions, process webhook events, and sync data across your tools effortlessly. With the TruGen.ai n8n integration, you can: * **Create and deploy AI agents** directly from your workflows * **Trigger automations from webhook events** generated by agent conversations * **Capture leads and qualification data** from inbound interactions * **Sync notes, contacts, and conversation outcomes** with CRMs like HubSpot or Salesforce * **Connect with 1000+ apps and services** through n8n’s workflow ecosystem * **Build end-to-end automations** for sales, support, recruiting, onboarding, and more See the TruGen.ai n8n integration documentation for setup instructions, available nodes, and workflow examples. Create and manage agents using no-code visual engine Official examples Official code repository # Widget Customization Source: https://docs.trugen.ai/docs/integrations/widget-customization Theme, position, and configure the TruGen embed widget: colors, buttons, layout, and domain restrictions. The widget config controls how the TruGen embed looks and behaves on your site. Every option below is set on the agent's `widget` object in the agent config, and can be edited in the Studio or via the API. ## The widget object The widget config lives on your agent under the `widget` field: ```json theme={null} { "agent_name": "My Agent", "widget": { "widget_type": "dual", "position": "full", "default_theme": "dark", "color": "#11E59E", "color_mode": "solid", "start_call_button_text": "Start Chat", "show_talk_button": true, "talk_button_text": "Talk", "show_chat_button": true, "chat_button_text": "Chat" } } ``` Everything on this page is a field on that object. ## Position Controls where the widget renders on the page. | Value | Behavior | | - | - | | `full` | Fills the entire container (used when embedded inline via iframe) | | `left` | Docks to the bottom-left corner as a floating widget | | `right` | Docks to the bottom-right corner as a floating widget | | `center` | Centered floating widget | | `center-mini` | Smaller centered variant | ```json theme={null} "widget": { "position": "right" } ``` Use `full` when you're dropping the agent into a dedicated section of your page (a whole panel or full page). Use `right` (or `left`) for the classic floating chat-widget look. ## Widget type and buttons The `widget_type` determines what the launcher shows the user before they start a session. | Value | What the launcher shows | | - | - | | `dual` | Both a **Talk** button (starts a voice/video call) and a **Chat** button (starts a text chat) | | `talk` | Only the Talk button | | `chat` | Only the Chat button | You can also individually toggle and rename the buttons: ```json theme={null} "widget": { "widget_type": "dual", "show_talk_button": true, "talk_button_text": "Talk to us", "show_chat_button": true, "chat_button_text": "Ask a question" } ``` The `start_call_button_text` field controls the primary call-to-action inside the widget (default: `"Start Chat"`). ## Theming ### Colors ```json theme={null} "widget": { "default_theme": "dark", "color_mode": "solid", "color": "#11E59E", "button_text_color": "#0B0B0B" } ``` | Field | Type | Description | | - | - | - | | `default_theme` | `"dark"` \| `"light"` | Base theme for the widget UI | | `color_mode` | `"solid"` \| `"gradient"` | Solid color or two-stop gradient | | `color` | hex string | Primary color (used when `color_mode: "solid"`) | | `gradient_color_start` | hex string | Gradient start (used when `color_mode: "gradient"`) | | `gradient_color_end` | hex string | Gradient end | | `button_text_color` | hex string | Foreground color for text on the primary button | ### Gradient example ```json theme={null} "widget": { "color_mode": "gradient", "gradient_color_start": "#11E59E", "gradient_color_end": "#5A7CFF", "button_text_color": "#0B0B0B" } ``` ## Branding Add your company logo, name, and supporting text to the widget: ```json theme={null} "widget": { "company_name": "Acme Corp", "company_logo": "https://assets.acme.com/logo.svg", "sub_text": [ "Powered by Acme" ] } ``` | Field | Type | Description | | - | - | - | | `company_name` | string | Displayed in widget header | | `company_logo` | URL | Public HTTPS URL to the logo image | | `sub_text` | string\[] | Additional lines shown under the header | | `agent_name` | string | Display name of the agent inside the widget | | `website_url` | string | Optional link back to your site from the widget | ## View mode ```json theme={null} "widget": { "view_mode": "iframe" } ``` | Value | Behavior | | - | - | | `iframe` | Widget renders inside an iframe on your page (fully isolated) | | `widget` | Widget renders in a shadow DOM directly in your page (shared page, isolated styles) | Use `iframe` for maximum isolation and simplicity. Use `widget` when you want the launcher to visually blend with your page. ## Suggested topics Show a short list of starter prompts under the widget's welcome UI to nudge users toward useful conversations. ```json theme={null} "widget": { "suggested_topics_enabled": true, "hide_suggested_topics": false, "initial_suggested_topics": [ "Tell me about your pricing", "How do I integrate the API?", "Book a demo" ] } ``` | Field | Type | Description | | - | - | - | | `suggested_topics_enabled` | boolean | Show the suggested-topics list at all | | `hide_suggested_topics` | boolean | Hide them by default; user can expand | | `initial_suggested_topics` | string\[] | The topics themselves | ## Allowed origins Control which domains are allowed to embed this agent's widget. **Only requests from the origins you list can load the widget and start a conversation with the agent**: every other domain is refused with `403 origin_not_allowed`. ```json theme={null} "widget": { "allowed_domains_enabled": true, "allowed_domains": [ "https://www.acme.com", "https://app.acme.com" ] } ``` | Field | Type | Description | | - | - | - | | `allowed_domains_enabled` | boolean | Turn the origin check on. When `false`, any origin can embed the widget. | | `allowed_domains` | string\[] | List of allowed origins. Only requests coming from these domains can load the widget and hold a conversation with the agent. Include the scheme (`https://`). | **Best practices** * Turn `allowed_domains_enabled: true` on for any production agent: otherwise anyone can embed your agent on their own site and consume your usage. * Include every origin the same agent will be used from: your marketing site, app, staging environment, etc. * Include the exact scheme (`https://` vs `http://`) and subdomain (`www.` matters). * After enabling, verify the widget still loads on every intended origin. ## Full example An agent with a floating right-side widget, gradient theming, both buttons visible, and domain restrictions on: ```json theme={null} "widget": { "widget_type": "dual", "position": "right", "view_mode": "widget", "default_theme": "dark", "color_mode": "gradient", "gradient_color_start": "#11E59E", "gradient_color_end": "#5A7CFF", "button_text_color": "#0B0B0B", "start_call_button_text": "Start Chat", "show_talk_button": true, "talk_button_text": "Talk", "show_chat_button": true, "chat_button_text": "Chat", "company_name": "Acme", "agent_name": "Support", "allowed_domains_enabled": true, "allowed_domains": [ "https://www.acme.com", "https://app.acme.com" ] } ``` ## Next steps Every prop the React widget accepts. Drop the React widget into your app in a few lines. # Embed via Widget Source: https://docs.trugen.ai/docs/integrations/widget-integration Let your customers learn about your product and services while having a fun and informative chat with TruGen video agents. The React widget drops into any React or Next.js app in a couple of lines. ## Get started Add the widget to your project with npm (or your preferred package manager). ```bash theme={null} npm install @aiteammate/agent-widget ``` Import the stylesheet and the `TrugenAgentWidget` component, then render it with your agent ID and user context. ```tsx theme={null} import "@aiteammate/agent-widget/styles.css"; import { TrugenAgentWidget } from "@aiteammate/agent-widget"; export default function TrugenWidget() { return ( ); } ``` Replace `agentId` with the ID of the agent you created in the [Developer Portal](https://app.trugen.ai), and swap `USER_NAME`, `USER_ID`, and `CONTEXT` with values that identify the end user and any session context you want the agent to have. ### More Resources Explore our official Github Repo for more examples # Widget SDK Reference Source: https://docs.trugen.ai/docs/integrations/widget-reference Every prop the @aiteammate/agent-widget React component accepts. The `@aiteammate/agent-widget` package exposes a single React component, `TrugenAgentWidget`. Its full appearance and behavior are configured server-side via the agent's [widget config](/docs/integrations/widget-customization): the props below are what you pass at render time from your app. ## Install ```bash theme={null} npm install @aiteammate/agent-widget ``` Import the stylesheet once (typically in your app's root layout): ```tsx theme={null} import "@aiteammate/agent-widget/styles.css"; ``` Then render the component with your agent ID: ```tsx theme={null} import { TrugenAgentWidget } from "@aiteammate/agent-widget"; export default function AgentPage() { return ( ); } ``` ## Props | Prop | Type | Required | Description | | - | - | - | - | | `agentId` | `string` | Yes | ID of the agent to load. Copy from the [Developer Portal](https://app.trugen.ai) or from `POST /v1/ext/agent`. | | `context` | `string` | No | Free-form context string appended to the agent's system prompt for this session. | | `userName` | `string` | No | Display name for the participant. Also passed to the agent so it can address the user by name. | | `userId` | `string` | No | Your internal user identifier. Attaches to the resulting `conversation` record for analytics and lookup. | ## Requirements * **React 19+**: the widget declares React 19 as a peer dependency * **Modern browser**: Chrome 90+, Edge 90+, Firefox 88+, Safari 14+ * **HTTPS**: camera and microphone access is only granted on HTTPS origins (or `localhost` in development) ## What's configured server-side Everything about how the widget looks (colors, position, buttons, branding, allowed domains) lives on the agent's `widget` config. Change it in the Studio or via the API and every embed of the widget picks up the change on the next session. Server-side settings covered on separate pages: * [Widget Customization](/docs/integrations/widget-customization): colors, position, buttons, branding * [Allowed origins](/docs/integrations/widget-customization#allowed-origins): only listed domains can embed the widget and hold a conversation * [System messages](/docs/agents/system-messages): welcome, idle, exit messages ## Next steps Configure colors, position, buttons, and branding for the widget. Full setup guide for the React widget. # Hawkeye-1 Source: https://docs.trugen.ai/docs/models/hawkeye-1 TruGen's Vision Action Recognition Model: the perception layer that gives AI agents the ability to see, hear, and understand humans in context. **Hawkeye-1 is TruGen's Vision Action Recognition Model**: a real-time perception system that goes far beyond conventional emotion detection. Instead of reducing human state to a handful of categories, Hawkeye-1 reads body language, vocal tone, subtle facial expressions, environmental cues, and conversational timing simultaneously to build a layered understanding of the person on the other side of the conversation.
Hawkeye-1 Vision Action Recognition Model
## The three pillars of Hawkeye-1 ### Multimodal perception Hawkeye-1 sees and listens in parallel. It combines what it observes on camera with what it hears in speech to form a unified, multimodal understanding of the user. This is what makes it a true perception system, not just a computer-vision model. ### Environmental awareness Context doesn't stop at the face. Hawkeye-1 continuously analyses the video feed, tracking environmental changes, detecting key gestures and behaviours, and triggering relevant actions as needed. Whether a user holds up a product for a visual question, steps away from the screen, or changes their surroundings, Hawkeye notices: and the agent adapts. ### Emotional intelligence Hawkeye-1 reads body language, vocal tone, and subtle facial expressions to render emotional understanding the way humans do: with real-time awareness of context and conversational flow. The result is an agent that doesn't just react to words, but responds to meaning. ## Developer-friendly by design Hawkeye-1 is built for integration. A single API flag enables vision perception, and natural-language prompts let you configure what to track: objects, gestures, on-screen activity, or all of the above. * **Enable Hawkeye with a single flag**: flip one parameter and your agent gains real-time scene analysis, effortlessly and precisely. * **Answer visual questions**: the model sees and understands the user's environment, responding to visual queries about objects, scenes, and actions just like a human would. * **Custom action triggers**: automate responses and fire tool calls at the right moment based on what Hawkeye perceives (timing, tone, gesture, or environment). ## What you can build with Hawkeye-1 Understand patient mood and engagement in real time. Trigger tool calls at the right moment based on timing, tone, and conversational flow. Avatars that gauge learner engagement, adjust pacing, and provide personalised guidance: making training more effective at scale. Handle FAQs and guide users through complex flows while reading frustration or confusion before it escalates. Qualify leads and showcase products with avatars that read buyer signals (hesitation, interest, objection) and adapt in real time. Screen candidates with adaptive interviews that evaluate answers, communication style, confidence, and engagement. ## Better together: Hawkeye-1 + Huma Hawkeye-1 is powerful on its own, but reaches its full potential when paired with the [Huma family](/docs/models/overview) of avatar renderers. Together they deliver: * **Visual realism + situational awareness**: Huma renders photorealistic faces; Hawkeye-1 adds real-time perception of who's watching. * **Emotionally aware + contextually responsive**: Huma expresses emotion through micro-expressions; Hawkeye-1 tells it exactly when and how. * **Real-time emotional sync**: expression, rhythm, and context synchronise into a single seamless conversational experience. The combination turns static chatbots into living, breathing video agents: capable of seeing, understanding, and responding with the nuance of a real human conversation. ## Key characteristics | Attribute | Detail | | - | - | | Modality | Continuous vision perception (camera + audio, in parallel) | | Input | Live user webcam and screen share | | Output | Structured scene, gesture, and emotional context passed to the LLM | | Detection | Emotion, gaze, head pose, face count, gestures, environment | | Activation | Single API flag on the agent configuration | ## Next steps How to enable Hawkeye-1 on your agent and configure what to track. See how Hawkeye-1 fits alongside the Huma family of renderers. # Huma-1 Source: https://docs.trugen.ai/docs/models/huma-1 TruGen's first avatar model to combine full-face rendering with real-time emotional control: powered by Gaussian Avatars. **Huma-1 is TruGen's first-generation avatar renderer**: the first model to combine full-face rendering with real-time emotional control. Powered by **Gaussian Avatars**, it captures every micro-expression, lip movement, blink, and emotional nuance to deliver hyper-realistic digital humans that don't just talk, but truly communicate.
Huma-1 and Huma-2 avatar models with Hawkeye-1 vision model
## Lightning-fast rendering Huma-1 renders the full face and expressions in **under 80 milliseconds**: fast enough to power seamless, two-way, real-time conversations without perceptible lag. Whether it's a customer support interaction or a coaching session, the experience feels natural and immediate. ## Emotion-aware expression engine Most avatar systems treat facial animation as a surface-level overlay. Huma-1 goes deeper. Its emotion-aware engine adapts expressions, tone, and micro-gestures based on conversational flow: meaning the avatar doesn't just match words to mouth shapes; it mirrors the emotional arc of the dialogue. The result is an avatar that feels genuinely responsive and alive. ## Full-face animation Huma-1 tackles the four pillars of believable facial animation: * **Micro-expressions**: subtle eyebrow shifts, gentle smiles, and involuntary cues that make faces feel alive * **Lip syncing**: perfect word-to-lip synchronisation in real time, making dialogue feel natural and fluid * **Eye blinking**: natural blink patterns that prevent the dead-stare effect plaguing most avatar systems * **Emotional presence**: avatars adjust reactions to reflect warmth, concern, excitement, or empathy in context ## Better together: Huma-1 + Hawkeye-1 Huma-1 doesn't work in isolation. Paired with [Hawkeye-1](/docs/agents/vision/overview) (our vision model), it gains the ability to understand context, emotion, and nuance from the person on the other side of the conversation. Hawkeye analyses tone, pacing, and intent, while Huma mirrors it with human-like timing and context-aware engagement. Together, they power conversational video agents that don't just respond: they connect. ## Key characteristics | Attribute | Detail | | - | - | | Modality | Real-time video generation | | Speech sync latency | ≤ 80 ms | | Rendering approach | Gaussian Avatars | | Expression fidelity | Micro-expressions, gaze, head motion, blink | | Output | Streamed video frames | ## Next steps Compare Huma-1 against Huma-2. The current default real-time renderer. # Huma-2 Source: https://docs.trugen.ai/docs/models/huma-2 How we built a real-time avatar with sub-500 ms latency: a full speech-to-animation pipeline built on Gaussian Splatting. **Huma-2 is TruGen's production real-time avatar renderer.** Building an interactive avatar that sees, listens, and responds like a human is a deceptively hard problem. The technical hurdles aren't just accuracy: they're speed. A beautiful avatar that lags by two seconds feels broken. Our target: complete the entire pipeline in under 500 ms. Two variables dominate every design decision: **latency** and **quality**. We found that smaller, faster models were the key to threading this needle without sacrificing the realism that makes an avatar believable. ## The pipeline A real-time avatar isn't a single model: it's an orchestrated chain of specialised systems working in parallel. Here's the architecture we settled on. Huma-2 real-time avatar pipeline architecture Each stage adds latency. Our job was to shrink every link in this chain: especially the lip sync model, which sits at the end and directly determines the perceived quality of the avatar. ## Choosing a lip sync architecture Lip sync is where realism lives or dies. We evaluated three broad families of architectures before committing to **Gaussian Splatting**. Its explicit scene representation makes it fast to render and straightforward to deform: exactly what we needed for a real-time, audio-driven animation system. Comparison of lip sync architecture families Training requires only 2–3 minutes of pre-recorded video in a controlled setting. This keeps data collection practical and accessible, without compromising model quality. ## Huma-1: the foundation Our first architecture, Huma-1, established the core two-step Gaussian pipeline. Huma-1 two-step Gaussian pipeline Huma-1 also introduced our two-phase runtime model, which became the foundation for all future work. Two-phase runtime: preloading and inference The preloading cost was significant: 20 to 30 seconds on a single GPU with 8 CPU cores. Acceptable for a prototype, but clearly a problem to solve for production deployments. ## Huma-2: rethinking every bottleneck Huma-2 is the result of systematically attacking every source of latency in Huma-1 (models, data loading, pre-processing) without sacrificing accuracy. The changes touch every layer of the system. ### Smaller models, bigger impact We redesigned our internal models to be significantly smaller than their Huma-1 counterparts. Fewer parameters means faster inference, and the accuracy trade-off turned out to be negligible: we stayed within acceptable quality bounds while gaining substantial speed. ### Minimised data loading and pre-processing The original pipeline had pre-processing stages that loaded more data than necessary and ran heavier operations than required. In Huma-2 we audited every step, replacing or eliminating pre-processing models that were overdoing it for our specific use case. The result is a leaner boot sequence with no loss in output quality. ### Smoother audio encoding A notable improvement in Huma-2 is robustness to variation in training data. The audio encoder now operates more smoothly across different recording conditions, making the model less sensitive to edge cases in the input data. This wasn't just a quality win: it simplified our data collection requirements significantly. ## Key takeaways After two generations of architecture, a few principles have proven durable. * **Gaussian Splatting offers a uniquely practical trade-off for avatar rendering**: fast enough for real-time use, flexible enough for audio-driven deformation, and trainable from short video clips. * **Splitting runtime into a preloading phase and an inference phase is a powerful design pattern.** Front-loading work that doesn't change between sessions is a reliable way to minimise perceived latency. * **Smaller models don't automatically mean worse models.** Careful architecture design and targeted reduction of pre-processing overhead can produce a faster, more robust system with comparable output quality. ## Next steps The first-generation renderer that Huma-2 was built on. Train your own Huma-2 avatar from 2–3 minutes of source video. # Models Source: https://docs.trugen.ai/docs/models/overview The Huma family of proprietary avatar-rendering models that power TruGen's real-time video agents. TruGen builds and runs its own foundation models. Two families live here: * The **[Huma family](#the-huma-family-at-a-glance)**: avatar renderers that turn audio into a photorealistic face. Two are in production today: **Huma-2** for real-time conversations, and **Huma-1** for high-expressiveness renders. * **[Hawkeye-1](/docs/models/hawkeye-1)**: the Vision Action Recognition Model that gives agents real-time perception of the user, their environment, and their emotional state. Together, Huma renders the face; Hawkeye reads the room. ## The Huma family at a glance | Model | Render pipeline | Best fit | | - | - | - | | **[Huma-2](/docs/models/huma-2)** | ≤ 500 ms audio → video | Real-time conversational agents. Default renderer. | | **[Huma-1](/docs/models/huma-1)** | Higher: optimised for expression fidelity | Async video generation, high-expressiveness renders | ## Huma-2 vs Huma-1 The two production models take different design trade-offs. Here's how they compare across the dimensions that matter for real deployments. | Dimension | Huma-2 | Huma-1 | | - | - | - | | **Primary use case** | Real-time conversation | Async video generation, expressive renders | | **End-to-end conversational latency** | ≤ 800 ms | Higher: not tuned for throughput | | **Render pipeline (audio → video)** | ≤ 500 ms | Longer per frame: optimised for expression | | **Rendering approach** | Gaussian Splatting with audio-driven facial deformation | First-generation neural avatar renderer | | **Source video required for custom avatars** | 2–3 minutes controlled recording | Longer, more constrained capture | | **Model footprint** | Leaner, faster inference | Larger, more expressive per-frame | | **Runtime** | Two-phase (preload + inference) | Single-phase render | | **Expression fidelity** | High: natural facial motion, gaze, micro-expressions | Highest: dense micro-expression and emotional nuance | | **Audio robustness** | Robust across recording conditions | Tuned for clean audio input | | **Availability** | Default on all new agents | Available on legacy agents | ## How the model fits in the pipeline Whichever Huma model you use, it sits at the end of TruGen's conversational pipeline: ``` User audio → STT → LLM → TTS → Huma → Video output ↑ Hawkeye-1 (vision context, in parallel) ``` Full breakdown in the [Realtime Pipeline](/docs/agents/pipeline). ## Next steps Real-time avatar renderer: architecture, characteristics, and how it renders your agent. First-generation expressive renderer. # Overview Source: https://docs.trugen.ai/docs/overview Build face-to-face AI agents that see, hear, and speak with your users in real time: powered by the Huma family of models.
TruGen conversational video pipeline: WebRTC capture, STT, Hawkeye-1 vision, LLM, TTS, Huma-2 render
**TruGen is a platform for building real-time AI video teammates**: agents that hold live, face-to-face conversations with your users through a photorealistic avatar. A teammate sees the user through their camera, hears them through their microphone, and answers with lip-synced speech in under a second: grounded in your data, wired to your tools, and speaking whichever of 60+ languages the user chose. Underneath: TruGen's proprietary **Huma** avatar renderer, the **Hawkeye** vision model, a fully pluggable **STT → LLM → TTS** pipeline, and enterprise-ready primitives for auth, sessions, and compliance. Ship with a single iFrame, a drop-in React widget, or the JavaScript / Python SDK: every path runs on the same infrastructure underneath. ## What you can build Handle inbound questions with brand-accurate answers grounded in your docs. Qualify inbound leads, demo products, and hand off to a human when the conversation calls for it. Run structured interviews, score responses, and produce transcripts you can review. Walk new hires or customers through a guided flow with vision-aware coaching. Collect symptoms, history, and consent before the appointment: in the patient's own language. Practice, correct, and coach with a patient teacher that never runs out of hours. Guide users through applications, KYC, and product selection with a calm, compliant voice. Turn any screen with a camera into a helpful teammate that greets and assists customers. Anywhere a human once had to have a conversation, an agent can. [See real-world examples →](/docs/examples/ai-interviewer) ## How it works Every agent runs through the same five-stage pipeline. Each stage is pluggable, and every stage can be configured per agent. The user's audio and video stream into the pipeline with sub-100 ms transport, from any modern browser or mobile web. Speech-to-text transcribes audio in real time. Hawkeye-1 analyses the video stream for gaze, gesture, and scene context: and hands both to the LLM. The language model generates a response using the agent's system prompt, attached knowledge base, memory, and available tools. Text-to-speech renders the response as natural, expressive audio in the language the user spoke. Huma-2 generates the avatar video frame-by-frame, synced to the audio, and streams both back to the user: closing the loop in under a second. [Read the full pipeline breakdown →](/docs/agents/pipeline) ## Performance characteristics | Metric | Value | | - | - | | End-to-end response latency (Huma-2) | ≤ 800 ms typical | | Huma-2 render pipeline | ≤ 500 ms (audio in → video out) | | Concurrent sessions | Scale-based; contact sales for high-concurrency plans | | Uptime target | 99.9% | | Supported languages | 60+ (see [multilingual](/docs/agents/multilingual-support)) | Numbers are measured on the default Groq + ElevenLabs stack. Latency and quality vary with your chosen LLM, TTS, and network path. ## Foundation models TruGen ships three proprietary models. Each has a specific job: combine them or use them independently. | Model | Role | Notes | | - | - | - | | **Huma-2** | Real-time avatar renderer | Gaussian-splatting based. Trainable from 2–3 min of source video. ≤ 500 ms render pipeline. | | **Huma-1** | Expressive avatar renderer (legacy) | Higher expressiveness at slightly higher latency. Recommended for pre-recorded video generation. | | **Hawkeye-1** | Vision action recognition | Continuous scene, gaze, gesture, and multi-face analysis fed into the LLM as context. | [Compare models in depth →](/docs/models/overview) ## Three ways to build Create, configure, and test an agent in the TruGen Studio. Ship with an iFrame in a single line. Drop the React widget into any app with an `agentId`. Full theming, no WebRTC handling. Use the JavaScript or Python SDK for custom UIs, custom event pipelines, or server-driven agent orchestration. ## Next steps Create your first agent and embed it in under 5 minutes. Understand what an agent is, how conversations flow, and what's configurable. # Attach to Agents Source: https://docs.trugen.ai/docs/presentations/attaching Wire your Visual Presentations to one or many agents via the Studio or via the agent API. A Visual Presentation sits idle until it's attached to an agent. Attach it in the Studio when creating or editing an agent, or via the API by including the presentation's ID in the agent's `visual_presentations` array. ## In the Studio Open the agent you want to attach the presentation to in [app.trugen.ai](https://app.trugen.ai). In the agent's configuration tabs, open **Visual Presentations**. Pick a single presentation deck (`.pdf` or `.pptx`) from your library to attach to the agent. Save the agent. The next session picks up the new presentation configuration automatically. ## Via API Include a presentation reference in the agent's `visual_presentations` array when creating or updating an agent: ```json theme={null} { "agent_name": "Sales Agent", "agent_system_prompt": "You present products and answer sales questions.", "visual_presentations": [ { "id": "5d7b525d-f7ef-44c5-9e49-422fdfdb9b2c" } ] } ``` An agent can be configured with one presentation deck (`.pdf` or `.pptx`) at a time. Full endpoint reference: [Create Agent](/api-reference/endpoint/agentcreate) and [Update Agent](/api-reference/endpoint/agentupdate). ## Next steps Create and manage presentation decks. Learn how slide presentation works in live agent sessions. # Setup Source: https://docs.trugen.ai/docs/presentations/creating Create a Visual Presentation in the Studio or via the API and name it so the agent can find it. Every Visual Presentation starts with a **name** and a **description**. Both fields matter because the agent reads them to decide *whether* to present this slide deck for a given user question. A vague name or an empty description means the LLM won't pick the presentation when relevant. ## In the Studio Go to [app.trugen.ai](https://app.trugen.ai) and click **Presentations** in the left panel under **Configure**. Click **Create New**. Give it a clear **Name** and a specific **Description**. Upload your presentation file (`.pdf` or `.pptx`). Click **Save & Create**. Content is queued for slide indexing. Once processing completes, the presentation is ready to attach to agents. ## Via API Upload and create a presentation with a name, description, and file: ```bash theme={null} curl --location 'https://api.trugen.ai/v1/ext/presentation' \ --header 'x-api-key: YOUR_API_KEY' \ --form 'name="Q3 Sales Deck"' \ --form 'description="Quarterly sales presentation for 2025. Use when asked about sales metrics, product growth, revenue targets, or Q3 results."' \ --form 'input=@/path/to/presentation.pdf' ``` The response returns a Presentation `id`: save it to attach the presentation to agents. ```json theme={null} { "id": "5d7b525d-f7ef-44c5-9e49-422fdfdb9b2c", "name": "Q3 Sales Deck", "description": "Quarterly sales presentation for 2025. Use when asked about sales metrics, product growth, revenue targets, or Q3 results.", "status": "pending" } ``` Requests use `multipart/form-data` because the endpoint accepts file uploads at creation time. Total request size is capped at **100 MB**. ## Naming and describing well The Name and Description drive retrieval routing. Write them clearly so the agent knows when to pick this deck over another. ### Good ``` Name: Sales-Deck-Q3 Description: Use this whenever the user asks about sales performance, Q3 targets, revenue breakdown, or sales strategies. ``` ``` Name: Architecture-Overview Description: Use this when the user asks about system architecture, server infrastructure, API flow, or backend components. ``` ### Bad ``` Name: Deck1 Description: Slides ``` Both are too vague. The LLM has no signal to pick this presentation. ## Managing your Presentations * **List all presentations**: `GET /v1/ext/presentation` * **Get a specific presentation**: `GET /v1/ext/presentation/{id}` * **Update presentation details**: `PATCH /v1/ext/presentation/{id}` * **Delete a presentation**: `DELETE /v1/ext/presentation/{id}` ## Next steps Learn how agents use presentations during live sessions. Combine Visual Presentations with text Knowledge Bases. # Presentations Source: https://docs.trugen.ai/docs/presentations/overview Give your agent a deck. When the user asks a relevant question, the agent presents the right slide alongside its spoken answer. **Visual Presentations** turn your agent into a presenter. Upload a PDF or PowerPoint deck to your library, attach the presentation to an agent, and when a user asks a question that matches the content, the agent shows the relevant slide while it speaks its answer. This turns typical "explain how X works" answers into an actual walkthrough: the agent shows the pricing slide when asked about pricing, the architecture diagram when asked how the system works, and so on. ## Supported media | Media | Formats | Size limit | Notes | | - | - | - | - | | **PDF** | `.pdf` | 100 MB | Upload a file or provide a public URL. Each page becomes a slide. | | **PowerPoint** | `.pptx` | 100 MB | Upload a file or provide a public URL. Each slide is indexed. | Each slide is indexed after upload: the agent uses semantic search to find the right slide based on the user's question, similar to how [Knowledge Base](/docs/agents/knowledge/overview) retrieval works. ## Creating a presentation In the Studio's agent creation flow, open the **Visual Presentations** tab. Pick a media kind (PDF or PowerPoint), upload the file, and give the presentation a name and optional tags. Uploads process asynchronously: PDFs are page-split and PowerPoints are slide-indexed. Status moves through `pending` → `processing` → `completed`. Once processing is complete, select the presentation in the tab and save the agent. It's now available for the agent to use in every session. ## How the agent uses it During a live session: 1. The user asks a question. 2. Before answering, the agent semantically searches the attached presentations for the most relevant slide. 3. If a strong match is found, the agent both **speaks the answer** and **presents the slide**: the widget shows the slide alongside the avatar. 4. If no strong match is found, the agent falls back to answering from its system prompt and knowledge base as normal: no presentation is shown. The agent decides when to present. You don't have to script it. ## Attaching to an agent Presentations are attached via the `visual_presentations` array on the agent config: ```json theme={null} { "agent_name": "Sales Agent", "visual_presentations": [ { "id": "presentation-uuid-1" }, { "id": "presentation-uuid-2" } ] } ``` Attach as many presentations as makes sense. The agent searches across all of them and picks the best match. ## Best practices * **Split large decks by topic.** A 100-slide master deck retrieves worse than 5 focused 20-slide decks. The agent picks the right presentation before it picks the right slide. * **Use clear slide titles.** Slide titles are heavily weighted in retrieval. "Q3 Pricing Update" is more findable than "Slide 12." * **Prefer PDF over PowerPoint** when the source allows. PDFs process faster and produce cleaner slide extractions. * **Test with real user questions.** After attaching, join a test session and ask 5–10 questions the way your users would. Watch which slides come up and which don't. ## Presentations vs Knowledge Base Both are retrieval-based, but they serve different purposes. | Use Knowledge Base for | Use Visual Presentations for | | - | - | | Text answers grounded in documents | Answers that need to *show* something visually | | FAQs, policies, product docs | Pitch decks, tutorials, product screenshots | | Long-form written content | Slide-per-idea material designed to be presented | You can (and often should) use both on the same agent. ## Next steps Create your first presentation in the Studio or via the API. Wire your presentations to one or many agents. # Providers Source: https://docs.trugen.ai/docs/providers/overview The external AI engines that power speech, language, and voice in TruGen's pipeline. TruGen integrates with industry-leading AI providers to power each stage of the conversational pipeline. Each provider handles one capability (STT, LLM, or TTS) and can be configured independently per agent. ## Speech-to-Text (STT) | Provider | Provider Key | Model | Model ID | Description | | - | - | - | - | - | | **Deepgram** | `lk-inference` | Flux General | `deepgram/flux-general-en` | Real-time English voice agent transcription | | **Deepgram** | `lk-inference` | Flux General Multilingual | `deepgram/flux-general-multi` | Real-time multilingual voice agent transcription | | **Deepgram** | `lk-inference` | Nova-3 | `deepgram/nova-3` | High-accuracy multilingual speech-to-text | | **AssemblyAI** | `lk-inference` | Universal-Streaming | `assemblyai/universal-streaming` | Real-time streaming transcription | | **AssemblyAI** | `lk-inference` | Universal-3.5 Pro | `assemblyai/universal-3-5-pro` | Real-time STT with conversation context | | **AssemblyAI** | `lk-inference` | Universal-Streaming Multilingual | `assemblyai/universal-streaming-multilingual` | Real-time multilingual code-switching STT | | **Speechmatics** | `lk-inference` | Speechmatics Enhanced | `speechmatics/enhanced` | High-accuracy global speech-to-text | | **Speechmatics** | `lk-inference` | Speechmatics Standard | `speechmatics/standard` | High-accuracy global speech-to-text | ## Large Language Models (LLM) | Provider | Provider Key | Model | Model ID | Description | | - | - | - | - | - | | **Groq** | `groq` | GPT OSS 20b | `openai/gpt-oss-20b` | Extremely fast, high-throughput reasoning model. By OpenAI. | | **Groq** | `groq` | GPT OSS 120b | `openai/gpt-oss-120b` | Fast, high-throughput OpenAI GPT reasoning model, great at tool calling. By OpenAI. | | **OpenAI** | `lk-inference` | GPT 5.4 Mini | `openai/gpt-5.4-mini` | Built for agentic workflows, fast latency, and excels in multimodal tasks. By OpenAI. | | **Google** | `lk-inference` | Gemini 4 31b | `google/gemma-4-31b-it` | Best for advanced reasoning, multimodal understanding, and agentic workflows. By Gemini. | | **Google** | `lk-inference` | Gemini 3.5 Flash Lite | `google/gemini-3.5-flash-lite` | Built for fast and efficient AI workflows. By Gemini. | | **Google** | `lk-inference` | Gemini 3.1 Flash Lite | `google/gemini-3.1-flash-lite` | Built for communication. By Gemini. | | **Kimi** | `lk-inference` | Kimi K2.6 | `moonshotai/kimi-k2.6` | Built for agents, multimodal capabilities, and fast inference. By Kimi. | ## Text-to-Speech (TTS) | Provider | Provider Key | Model | Model ID | Description | | - | - | - | - | - | | **ElevenLabs** | `elevenlabs` | Turbo 2 | `eleven_turbo_v2` | Low latency and fast English TTS | | **ElevenLabs** | `elevenlabs` | Turbo v2.5 | `eleven_turbo_v2_5` | Low latency and fast multilingual TTS | | **Cartesia** | `lk-inference` | Sonic 3 | `cartesia/sonic-3` | Best for streaming TTS | | **Cartesia** | `lk-inference` | Sonic 3.5 | `cartesia/sonic-3.5` | Next-generation real-time streaming TTS | | **Rime** | `lk-inference` | Mist v3 | `rime/mistv3` | Low latency and enterprise-grade TTS | | **Rime** | `lk-inference` | Coda | `rime/coda` | Low latency and enterprise-grade TTS | | **Fish Audio** | `lk-inference` | S2 Pro | `fishaudio/s2-pro` | State of the art expressive TTS | | **Fish Audio** | `lk-inference` | S2.1 Pro | `fishaudio/s2.1-pro` | State of the art expressive TTS | | **Inworld TTS** | `lk-inference` | Inworld TTS 1.5 Mini | `inworld/inworld-tts-1.5-mini` | State of the art character & interactive dialog TTS | New providers and model configurations are added regularly. Use the `/v1/providers` endpoint to always fetch the latest available list. ## Provider Types | Type | Role | | - | - | | `llm` | Large Language Model: reasoning and response generation | | `stt` | Speech-to-Text: real-time audio transcription | | `tts` | Text-to-Speech: voice rendering | ## Retrieve All Providers Use this endpoint to fetch all currently available providers and their models: **GET** `/v1/providers` ```bash Request theme={null} curl --request GET \ --url https://api.trugen.ai/v1/ext/providers \ --header 'Content-Type: application/json' \ --header 'x-api-key: ' ``` Replace `` with your API key from the Developer Portal. ## Next steps Connect a self-hosted or custom LLM to your agents. Configure STT and TTS languages for global conversations. # Quickstart Source: https://docs.trugen.ai/docs/quickstart Create your first TruGen agent via API and embed it in under five minutes. Create a conversational video agent with the REST API, then drop it into any web page. This uses platform defaults for every advanced setting: you'll tune those later. ## Prerequisites * A TruGen API key from the [Developer Portal](https://app.trugen.ai) * An avatar ID: the [Avatar Gallery](/docs/avatars/gallery) has stock avatars you can use right away ## 1. Create an agent Send a `POST /v1/ext/agent` with a name, prompt, and avatar. Everything else falls back to platform defaults (Groq LLM, ElevenLabs voice + STT, English, no tools). ```bash cURL theme={null} curl --request POST \ --url https://api.trugen.ai/v1/ext/agent \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data '{ "agent_name": "My First Agent", "agent_system_prompt": "You are a friendly assistant that answers questions in one or two short sentences.", "avatars": [ { "avatar_key_id": "665a1170" } ] }' ``` The response returns an `id`: save it for step 2. ```json Response theme={null} { "id": "agt_12345example", "message": "Agent created successfully" } ``` Need every configurable field? See the [full configuration reference](/api-reference/endpoint/agentcreate). ## 2. Embed the agent Pick the integration that matches your stack. Install the widget: ```bash theme={null} npm install @aiteammate/agent-widget ``` Render it with your agent ID: ```tsx theme={null} import "@aiteammate/agent-widget/styles.css"; import { TrugenAgentWidget } from "@aiteammate/agent-widget"; export default function AgentPage() { return ( ); } ``` Drop this into any HTML page: ```html theme={null} ``` For custom UIs and full session control: ```bash theme={null} npm install @trugen/js-sdk ``` ```typescript theme={null} import { createClient, TruGenEvent } from "@trugen/js-sdk"; // Get a session token from your backend (never expose your API key to the browser) const token = await fetch("/api/session-token") .then((r) => r.json()) .then((d) => d.token); const session = await createClient({ token }); session.on(TruGenEvent.VIDEO_STREAM_STARTED, (track) => { track.attach(document.getElementById("avatarVideo")); }); await session.connect(); ``` See the [JavaScript SDK quickstart](/docs/sdks/javascript/quickstart) for a working end-to-end example. Open the page in a browser and grant camera + mic permissions. Your agent joins the call and starts speaking. ## What just happened **Step 1: Agent created.** Behind that single API call, TruGen provisioned a persistent agent with your prompt and avatar, wired up the default pipeline (Groq LLM, ElevenLabs STT + TTS, English, turn detection on), and returned an ID. That ID is your handle to the agent everywhere: widget, iframe, SDK, external meetings, and API. Change the agent's behavior anytime with `PATCH /v1/ext/agent/{id}` and the next session picks it up. No redeploy of your app required. **Step 2: Live conversation.** The widget or iframe traded your API key for a short-lived session token, opened a WebRTC connection to TruGen's edge, streamed the user's microphone in, and streamed the rendered avatar video back. Every turn ran through the full pipeline (capture → STT → Hawkeye vision → LLM → TTS → Huma render) server-side in under a second. You wrote zero WebRTC code, managed zero media state, and never exposed your API key to the browser. ## Next steps What an agent is, how the conversation loop works, and everything you can configure. Write system prompts that behave well in a spoken, real-time setting. # Bring Your Own LLM Source: https://docs.trugen.ai/docs/resources/byo-llm Connect any OpenAI-compatible LLM (self-hosted, fine-tuned, or third-party) while keeping the rest of the TruGen pipeline intact. TruGen lets you replace the default LLM with any **OpenAI-compatible** endpoint. Everything else (STT, TTS, avatar rendering, tools, knowledge base) keeps working. Use this for compliance, fine-tuned models, or your own inference infrastructure. ## Why bring your own LLM | Benefit | Description | | - | - | | **Customisation** | Use a domain-specific fine-tune for better vertical accuracy | | **Data residency** | Keep sensitive data inside your own infrastructure or private cloud | | **Compliance** | Meet regulatory requirements around auditing and data handling | | **Cost control** | Choose your own provider or run on your own hardware | ## Requirements Your endpoint must implement the **OpenAI Chat Completions** specification: * **Endpoint:** `POST /chat/completions` * **Payload:** accepts a `messages: []` array * **Streaming:** Server-Sent Events (SSE) with `data:` framing **Optional: required only for specific features:** * **Function calling**: needed if the agent uses tools * **Vision**: needed for multimodal inputs ## Configure via the Developer Portal Navigate to **Create New Agent** or an existing agent in [app.trugen.ai](https://app.trugen.ai). Find the **LLM** section. In the Provider dropdown, select **Bring your own LLM**. Provide your **API URL**, **Model Name**, and **API Token**. Save. Bring Your Own LLM configuration in Developer Studio ## Configure via API Set the LLM config's `provider` to `"custom"`: ```json theme={null} "llm": { "provider": "custom", "model": "MODEL_NAME", "url": "https://your-inference.example.com/v1", "token": "YOUR_ENDPOINT_TOKEN" } ``` That's the only change needed. The rest of your agent configuration is unchanged. Full request example: ```bash theme={null} curl --request POST \ --url https://api.trugen.ai/v1/ext/agent \ --header 'Content-Type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data '{ "agent_name": "Custom LLM Agent", "agent_system_prompt": "You are a helpful assistant.", "avatars": [ { "avatar_key_id": "665a1170", "llm": { "provider": "custom", "model": "your-fine-tune-v1", "url": "https://your-inference.example.com/v1", "token": "YOUR_ENDPOINT_TOKEN" } } ] }' ``` ## Endpoint contract Your `/chat/completions` handler receives: ```json theme={null} POST /chat/completions { "model": "your-fine-tune-v1", "messages": [ { "role": "system", "content": "You are a helpful assistant." }, { "role": "user", "content": "What are your business hours?" } ], "stream": true, "tools": [ /* ... */ ] } ``` And must respond with an SSE stream: ``` data: {"id":"…","object":"chat.completion.chunk","choices":[{"delta":{"content":"We"},"index":0}]} data: {"id":"…","object":"chat.completion.chunk","choices":[{"delta":{"content":"'re open"},"index":0}]} data: {"id":"…","object":"chat.completion.chunk","choices":[{"delta":{"content":" Monday to Friday."},"index":0,"finish_reason":"stop"}]} data: [DONE] ``` ## Keep-alive during long generations Long generations without any output can trigger idle timeouts. Emit a comment line every 10 seconds: ``` : keep-alive ``` ## Function calling If your endpoint supports OpenAI-style function calling, return tool calls in the delta: ```json theme={null} { "choices": [ { "delta": { "tool_calls": [ { "index": 0, "id": "call_abc", "function": { "name": "check_order_status", "arguments": "{\"orderId\": \"ORD-9821\"}" } } ] } } ] } ``` TruGen invokes the tool, sends the result back as a follow-up `messages[].role: "tool"` turn, and continues generation. ## Fallback to a hosted model If your custom endpoint errors or times out, TruGen can fall back to a hosted model automatically: ```json theme={null} "llm": { "provider": "custom", "model": "your-fine-tune-v1", "url": "https://your-inference.example.com/v1", "token": "YOUR_ENDPOINT_TOKEN", "fallback_provider": "groq", "fallback_model": "openai/gpt-oss-120b" } ``` Strongly recommended for production: a single infrastructure hiccup on your side shouldn't kill live sessions. ## Latency expectations Custom LLMs add network round-trip time between TruGen's infrastructure and yours. Aim for: * **Time to first token:** under 500 ms * **Endpoint region:** as close to your TruGen region as possible * **Network latency to TruGen edge:** under 50 ms If your endpoint is in a different continent, latency will noticeably degrade the conversation. ## What's next Compare hosted providers if BYO isn't a hard requirement. Write prompts that work well for real-time voice. Enable function calling on your custom LLM. # Authentication Source: https://docs.trugen.ai/docs/sdks/javascript/authentication Secure your API keys and manage session tokens. TruGen AI uses a two-tier authentication system: API keys for server-side requests and session tokens for client-side connections. ## Tier 1: API Key Your API key is used to authenticate server-side requests to the TruGen AI API. API keys can be created and managed from the [TruGen AI Dashboard](https://app.trugen.ai/). ### Creating an API Key From the [API Keys page](https://app.trugen.ai/api-keys), click **Create API Key**, give it a name, and click **Create**. Copy and store it securely: you will not be able to view it again. Never expose your API key on the client side. Store and use it only on your server. If you lose your API key, you will need to create a new one: they cannot be recovered. ## Tier 2: Session Tokens Session tokens are temporary JWT credentials (valid for 5 minutes) that allow client applications to connect to TruGen's streaming infrastructure without exposing your API key. ### How Session Tokens Work Your server requests a session token from TruGen AI using your API key and agent configuration. TruGen AI generates a temporary JWT token (valid for 5 minutes) tied to your specific agent configuration. Your client uses the session token with the TruGen SDK to establish a direct WebRTC connection. Once connected, the client can send messages and receive video/audio streams directly. ### Creating Session Tokens Below is a basic Express server that exposes an endpoint for creating session tokens. ```javascript server.js theme={null} const express = require("express"); const app = express(); app.use(express.json()); app.post("/api/session-token", async (req, res) => { try { const response = await fetch("https://api.trugen.ai/v1/auth/conversation", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.TRUGEN_API_KEY, }, body: JSON.stringify({ agentId: process.env.AGENT_ID, }), }); if (!response.ok) { const errorData = await response.json(); console.error("Token creation failed:", errorData); return res.status(response.status).json({ error: "Token creation failed" }); } const { token } = await response.json(); res.json({ token }); } catch (error) { console.error("Network error:", error); res.status(500).json({ error: "Failed to create session token" }); } }); app.listen(3000, () => console.log("Server running on port 3000")); ``` ```typescript server.ts theme={null} import express, { Request, Response } from "express"; interface AgentConfig { agentId: string; } interface SessionTokenResponse { token: string; } const app = express(); app.use(express.json()); app.post("/api/session-token", async (_req: Request, res: Response) => { try { const response = await fetch("https://api.trugen.ai/v1/auth/conversation", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.TRUGEN_API_KEY as string, }, body: JSON.stringify({ agentId: process.env.AGENT_ID, } satisfies AgentConfig), }); if (!response.ok) { const errorData = await response.json(); console.error("Token creation failed:", errorData); return res.status(response.status).json({ error: "Token creation failed" }); } const { token }: SessionTokenResponse = await response.json(); res.json({ token }); } catch (error) { console.error("Network error:", error); res.status(500).json({ error: "Failed to create session token" }); } }); app.listen(3000, () => console.log("Server running on port 3000")); ``` ### Client-Side Usage Once your server creates and returns the session token, pass it to your client application to initialize the SDK and start streaming. See the [Basic JavaScript Example](/docs/sdks/javascript/examples/basic-javascript) and [Basic Usage](/docs/sdks/javascript/reference/basic-usage) guides for client-side integration examples. ### Dynamic Agent Configuration Instead of using the same agent for all users, you can pass the `agentId` dynamically from the client: #### User-based Agent Selection ```typescript theme={null} app.post("/api/session-token", async (req: Request, res: Response) => { const { agentId } = req.body; if (!agentId) { res.status(400).json({ error: "agentId is required" }); return; } const response = await fetch("https://api.trugen.ai/v1/auth/conversation", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.TRUGEN_API_KEY as string, }, body: JSON.stringify({ agentId }), }); const { token } = await response.json(); res.json({ token }); }); ``` #### Client-side: passing agentId dynamically ```typescript theme={null} const response = await fetch("/api/session-token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ agentId: "your-agent-id" }), }); const { token } = await response.json(); ``` ### Environment Setup Store your configuration securely in a `.env` file on your backend server: ```ini .env theme={null} TRUGEN_API_KEY=your-api-key-here # Only needed if using a fixed agent (non-dynamic approach) AGENT_ID=your-agent-id-here ``` # Basic JavaScript Example Source: https://docs.trugen.ai/docs/sdks/javascript/examples/basic-javascript Get your first AI avatar running using a JavaScript Node server. The TruGen API provides a simple interface for implementing digital AI avatars within your web applications. This guide will walk you through the process of setting up a minimal example of an interactive AI avatar using a JavaScript server. ## Prerequisites * A TruGen API key (get one [here](https://app.trugen.ai/api-keys)) * A TruGen Agent ID (create and get one [here](https://app.trugen.ai/teammate-library)) * Node.js installed on your machine * A modern web browser with microphone access ## Project Setup ```bash theme={null} npm init -y npm install express dotenv @trugen/js-sdk ``` Create the following directory layout: ```text theme={null} project/ ├── .env ├── server.js ├── public/ │ └── index.html └── package.json ``` Create a `.env` file and add your API key and Agent ID: ```env theme={null} TRUGEN_API_KEY=your-api-key-here AGENT_ID=your-agent-id-here ``` Never expose your API key in the browser. The server reads it from `.env` and returns only a short-lived session token to the client. Create `server.js`: this keeps your API key on the server and returns a session token to the browser: ```javascript theme={null} const express = require("express"); require("dotenv").config(); const app = express(); app.use(express.json()); app.use(express.static("public")); app.post("/api/session-token", async (req, res) => { try { const response = await fetch("https://api.trugen.ai/v1/auth/conversation", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.TRUGEN_API_KEY, }, body: JSON.stringify({ agentId: process.env.AGENT_ID, }), }); if (!response.ok) { const errorData = await response.json(); console.error("Token creation failed:", errorData); return res.status(response.status).json({ error: "Token creation failed" }); } const { token } = await response.json(); res.json({ token }); } catch (error) { console.error("Network error:", error); res.status(500).json({ error: "Failed to create session token" }); } }); app.listen(3000, () => console.log("Server running at http://localhost:3000")); ``` Create `public/index.html`: ```html theme={null} Hello TruGen

Chat with your AI Avatar

Your avatar will appear below once connected

Ready

```
```bash theme={null} node server.js ``` Navigate to `http://localhost:3000` in your browser, allow microphone access when prompted, then click **Connect**.
# Basic TypeScript Example Source: https://docs.trugen.ai/docs/sdks/javascript/examples/basic-typescript Get your first AI avatar running using a TypeScript Express server. This guide will walk you through setting up a minimal example of an interactive AI avatar using a backend built with TypeScript and Express. ## Prerequisites * A TruGen API key (get one [here](https://app.trugen.ai/api-keys)) * A TruGen Agent ID (create and get one [here](https://app.trugen.ai/teammate-library)) * Node.js installed on your machine * A modern web browser with microphone access ## Project Setup Initialize a new project and install the required runtime and development dependencies: ```bash theme={null} npm init -y npm install express dotenv @trugen/js-sdk npm install -D typescript ts-node @types/express @types/node ``` Create a `tsconfig.json` file in the root of your project: ```json theme={null} { "compilerOptions": { "target": "ES2020", "module": "commonjs", "lib": ["ES2020"], "strict": true, "esModuleInterop": true, "skipLibCheck": true, "outDir": "dist", "rootDir": "." }, "include": ["server.ts"], "exclude": ["node_modules", "dist"] } ``` Set up the following directory layout: ```text theme={null} project/ ├── .env ├── server.ts ├── public/ │ └── index.html ├── tsconfig.json └── package.json ``` Create a `.env` file and add your API key and Agent ID: ```env theme={null} TRUGEN_API_KEY=your_trugen_api_key AGENT_ID=your_agent_id ``` Never expose your API key in the browser. The server reads it from `.env` and returns only a short-lived session token to the client. Create `server.ts`: this fetches the session token on the backend to keep your credentials secure: ```typescript theme={null} import express, { Request, Response } from "express"; import path from "path"; import dotenv from "dotenv"; dotenv.config(); const app = express(); app.use(express.static("public")); app.get("/token", async (_req: Request, res: Response): Promise => { try { const response = await fetch("https://api.trugen.ai/v1/auth/conversation", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.TRUGEN_API_KEY as string, }, body: JSON.stringify({ agentId: process.env.AGENT_ID, }), }); const data = await response.json() as { token: string }; res.json({ token: data.token }); } catch (error) { console.error(error); res.status(500).json({ error: "Failed to create session token" }); } }); app.listen(3000, () => { console.log("Server running at http://localhost:3000"); }); ``` Create `public/index.html`. The frontend runs plain browser JS and imports the SDK from esm.sh directly, so no TypeScript compilation is required for the client side: ```html theme={null} TruGen SDK Test (TS)

TruGen SDK Test (TypeScript Server)



```
Start the server with `ts-node` for quick testing without a separate build step: ```bash theme={null} npx ts-node server.ts ``` Open `http://localhost:3000` in your web browser, allow microphone access, and click **Connect**.
# JavaScript SDK Source: https://docs.trugen.ai/docs/sdks/javascript/overview Build web applications with TruGen AI avatars using the JavaScript SDK. The TruGen JavaScript SDK lets you embed interactive AI avatars directly into your web application. It handles the WebRTC connection, audio streaming, and event system: so you can focus on building your experience. ```bash theme={null} npm install @trugen/js-sdk ``` Or import directly in the browser via CDN: ```html theme={null} ``` ## When to Use the SDK | Use Case | Recommended Approach | | - | - | | Custom UI with full control over the session | **JavaScript SDK** | | Fine-grained event handling and audio management | **JavaScript SDK** | | Quick embed with no code | [iFrame](/docs/integrations/embed-via-iFrame) or [Widget](/docs/integrations/widget-integration) | ## What the SDK Provides * **Session management**: create, connect, and disconnect avatar sessions * **Real-time events**: listen for speaking, transcript, connection, and mic events * **Audio control**: mute, unmute, switch devices, and inject custom audio * **Media access**: direct access to WebRTC video and audio tracks * **Raw frame processing**: feed frames into custom pipelines or canvas layouts ## What's Next? Get your first AI avatar running in under 5 minutes. Learn how to secure your API key with server-side session tokens. Full working examples in JavaScript and TypeScript. Complete SDK reference for all methods and events. # Usage in Production Source: https://docs.trugen.ai/docs/sdks/javascript/production Securely deploy TruGen AI in production environments. When deploying to production, do not expose your API key publicly. Instead: 1. Exchange your API key for a short-lived session token on the server side. 2. Pass this token to the client. 3. Initialize the TruGen SDK with the session token. ## Getting a Session Token Session tokens are valid for 5 minutes by default. You should request a new token for each user session rather than caching tokens long-term. The session token endpoint must be called from your server, not from client-side code. Making this request from the browser would expose your API key. ### Fetching a Session Token on Your Server From your server, make a request to get a session token by referencing your Agent ID (create and get one [here](https://app.trugen.ai/teammate-library)): ```typescript server.ts theme={null} interface SessionTokenResponse { token: string; } interface SessionTokenOptions { userName?: string; userId?: string; } async function getSessionToken( apiKey: string, agentId: string, options?: SessionTokenOptions ): Promise { const response = await fetch("https://api.trugen.ai/v1/auth/conversation", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": apiKey, }, body: JSON.stringify({ agentId, userName: options?.userName, userId: options?.userId, }), }); if (!response.ok) { const error = await response.text(); throw new Error(`Failed to get session token: ${response.status} ${error}`); } const data: SessionTokenResponse = await response.json(); return data.token; } ``` ```javascript server.js theme={null} async function getSessionToken(apiKey, agentId, options) { const response = await fetch("https://api.trugen.ai/v1/auth/conversation", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": apiKey, }, body: JSON.stringify({ agentId, userName: options?.userName, userId: options?.userId, }), }); if (!response.ok) { const error = await response.text(); throw new Error(`Failed to get session token: ${response.status} ${error}`); } const data = await response.json(); return data.token; } ``` *** ## User Identity Configuration When generating a session token, you can optionally provide details about the user connecting to the conversation session: * **`userName`**: A string representing the user's name (defaults to `"JS SDK"` if omitted). * **`userId`**: A unique string identifying the user. If omitted, the SDK automatically generates a timestamp-based ID (e.g. `usr_2026_06_25t12_49_49_168175`). These values are passed inside the JSON request body when calling `https://api.trugen.ai/v1/auth/conversation`. ### Example Request Body ```json theme={null} { "agentId": "your-agent-id-here", "userName": "Alice Smith", "userId": "user_alice_123" } ``` *** ## Common Error Responses | Status Code | Meaning | Solution | | :- | :- | :- | | **400** | Invalid request body or malformed `agentId` | Check your request body format or verify your Agent ID is a valid UUID | | **401** | Invalid, missing, or expired API Key | Verify your API key is correct and included in the `X-API-Key` header | | **500** | Agent not found or database error | Verify that the Agent ID exists and belongs to your account | # Quickstart Source: https://docs.trugen.ai/docs/sdks/javascript/quickstart Get your first AI avatar running in under 5 minutes. The TruGen API provides a simple interface for implementing digital AI avatars within your web applications. This guide will walk you through the process of setting up a minimal example of an interactive AI avatar. By the end, you'll have a working avatar that can have real-time conversations in your web browser. ## Prerequisites * A TruGen API key (get one [here](https://app.trugen.ai/api-keys)) * A TruGen Agent ID (create and get one [here](https://app.trugen.ai/teammate-library)) * A modern web browser with microphone access * A local web server (we'll show you how to start one below) ## Create Your First Avatar Create a new file called `index.html` and add this basic layout to display the avatar video and session status: ```html theme={null} Hello TruGen

Chat with your AI Avatar

Your AI avatar will appear below and start automatically

Loading...
```
Add the script that will automatically authenticate and start your session. Add this ` ``` Replace `your-api-key-here` and `your-agent-id-here` in the script block with your actual TruGen credentials. This quickstart puts credentials directly in the browser for simplicity. For production deployments, always keep your API key on the server. See [Usage in Production](/docs/sdks/javascript/production) for the secure approach. To serve your HTML file, start a local web server in the directory containing `index.html`: ```bash Python theme={null} python -m http.server 8000 ``` ```bash Node (npx) theme={null} npx serve ``` 1. Navigate to `http://localhost:8000` (or the port specified by your local server) in your browser. 2. Allow microphone access when prompted. 3. The avatar will load, connect, and start speaking automatically!
## What just happened? * **Session Token**: Your API key was exchanged for a temporary session token that enables the avatar connection. * **WebRTC Stream**: The TruGen SDK established a real-time WebRTC video/audio stream with the TruGen server. * **Voice Interaction**: Your avatar starts listening to your microphone input and automatically responds with natural real-time dialogue and expressions. ## What's Next? Learn how to secure your API key using server-side session tokens. Full example with a Node.js backend and clean connect/disconnect flow. SDK reference for initializing, streaming, and disconnecting. Listen to connection, speaking, and transcript events in real time. # Audio Control Source: https://docs.trugen.ai/docs/sdks/javascript/reference/audio-control Manage microphone inputs, mute states, and audio injection. The TruGen JS SDK provides utility methods to control the user's microphone state and programmatically upload or stream custom audio files to the avatar. ## Microphone Management ### Start/Stop Microphone Programmatically start or stop the microphone capturing session: ```typescript theme={null} // Start microphone capture await session.startMic(); // Stop microphone capture await session.stopMic(); ``` ### Muting and Unmuting Mute or unmute microphone inputs without tearing down the audio track: ```typescript theme={null} // Mute the microphone const stateAfterMute = session.muteInputAudio(); console.log("Is muted:", stateAfterMute.isMuted); // true // Unmute the microphone const stateAfterUnmute = session.unmuteInputAudio(); console.log("Is muted:", stateAfterUnmute.isMuted); // false ``` ### Get Microphone State Get the current mute and permission state of the user's microphone: ```typescript theme={null} const state = session.getInputAudioState(); console.log("Mute state:", state.isMuted); console.log("Permission state:", state.permissionState); // 'granted' | 'denied' | 'pending' ``` ### Change Audio Input Device Change the active microphone input device by passing its `deviceId`: ```typescript theme={null} // Change audio input device const deviceId = "your-audio-input-device-id"; await session.changeAudioInputDevice(deviceId); ``` *** ## Audio Injection You can inject custom audio clips (e.g., pre-recorded user voice message files) directly into the conversation stream. The SDK automatically handles switching back to the user's microphone once the custom audio injection completes. ### Upload Audio File Inject a standard audio file (`File` or `Blob` format): ```typescript theme={null} const fileInput = document.querySelector('input[type="file"]'); fileInput.addEventListener('change', async (e) => { const file = e.target.files[0]; if (file) { try { console.log("Injecting audio file..."); await session.uploadAudio(file); console.log("Audio file injected successfully"); } catch (err) { console.error("Failed to inject audio file:", err); } } }); ``` ### Send Audio Blob Send raw audio data as a `Blob`: ```typescript theme={null} // Inject audio blob directly await session.sendAudio(audioBlob); ``` # Basic Usage Source: https://docs.trugen.ai/docs/sdks/javascript/reference/basic-usage Install, setup, and deploy the TruGen AI JavaScript SDK. ## Installation Install the SDK in your project using npm: ```bash theme={null} npm install @trugen/js-sdk ``` ### Browser Requirements The TruGen SDK uses WebRTC for real-time video and audio streaming. Ensure your target browsers support: * WebRTC (Chrome 56+, Firefox 44+, Safari 11+, Edge 79+) * MediaDevices API for microphone access ### HTML Setup This example requires a video element to display the persona: ```html theme={null} ``` * `autoplay` starts the stream when the page loads. * `playsinline` prevents fullscreen mode on mobile devices. *** ## Basic Usage To keep your API key secure, exchange it for a short-lived session token on your server before initializing the client. See [Usage in Production](/docs/sdks/javascript/production) for detailed session token information. ### Initialize the Client Use `createClient` with your session token: ```typescript theme={null} import { createClient } from "@trugen/js-sdk"; const session = await createClient({ token: sessionToken }); ``` ### Start Streaming To start streaming the avatar, register a video stream event listener to attach the track to your video element, then connect the session: ```typescript theme={null} import { TruGenEvent } from "@trugen/js-sdk"; // Listen for the stream starting event session.on(TruGenEvent.VIDEO_STREAM_STARTED, (track) => { const videoElement = document.getElementById("avatarVideo"); track.attach(videoElement); }); // Connect to the streaming server try { await session.connect(); } catch (error) { console.error("Failed to start stream:", error); } ``` ### Listen for Events Handle connection lifecycle and speaking events using the `TruGenEvent` enum: ```typescript theme={null} import { TruGenEvent, ConnectionClosedCode } from "@trugen/js-sdk"; // Connection status events session.on(TruGenEvent.CONNECTION_ESTABLISHED, () => { console.log("Connected to avatar"); }); session.on(TruGenEvent.CONNECTION_CLOSED, (code: ConnectionClosedCode, reason: string) => { console.log("Connection closed:", code, reason); }); // Agent interaction events session.on(TruGenEvent.AGENT_SPEAKING_STARTED, () => { console.log("Avatar started speaking"); }); session.on(TruGenEvent.AGENT_SPEAKING_ENDED, () => { console.log("Avatar finished speaking"); }); ``` ### Stopping a Stream To stop an active session and release media resources: ```typescript theme={null} await session.disconnect(); ``` *** ## Custom Track and Frame Processing For advanced use cases, the SDK provides low-level getters and event helpers to access WebRTC media tracks and raw video frames. ### Accessing Media Tracks Get direct access to the underlying LiveKit track instances once the session is connected: ```typescript theme={null} // Returns RemoteVideoTrack | null const videoTrack = session.getVideoTrack(); // Returns RemoteAudioTrack | null const audioTrack = session.getAudioTrack(); ``` ### Track Subscriptions Use callbacks to listen for track updates. These helpers automatically execute the callback if the track is already active, and return an unsubscribe function: ```typescript theme={null} // Subscribe to video tracks const unsubscribeVideo = session.onVideoTrack((track) => { console.log("Active video track received:", track); track.attach(document.getElementById("avatarVideo")); }); // Subscribe to audio tracks const unsubscribeAudio = session.onAudioTrack((track) => { console.log("Active audio track received:", track); }); // Later, unsubscribe to stop listening unsubscribeVideo(); unsubscribeAudio(); ``` ### Processing Raw Video Frames If you need to feed video frames into a custom canvas layout, AI processing pipeline, or video filters, use `onVideoFrame`. It decodes and emits raw frames (using `VideoFrame` via browser WebCodecs if supported, or falling back to canvas-rendered `ImageData` frames) and returns an unsubscribe function: ```typescript theme={null} const unsubscribeFrame = session.onVideoFrame((frame) => { // Process each raw frame (VideoFrame or ImageData object) console.log("Received raw video frame:", frame); // Remember to call frame.close() if it's a WebCodecs VideoFrame to prevent memory leaks if (typeof frame.close === "function") { frame.close(); } }); // Later, unsubscribe to stop processing frames unsubscribeFrame(); ``` # Event Handling Source: https://docs.trugen.ai/docs/sdks/javascript/reference/event-handling Listen and respond to WebRTC streaming and conversation events. The TruGen JS SDK client is an `EventEmitter` that allows you to listen to real-time session state, media streams, user speaking, and agent avatar activity. ## Adding Event Listeners Register event listeners after creating the TruGen client and before starting the session with `connect()`. Event handlers must be registered before the session starts. Startup events such as microphone permission, connection, and stream initialization can fire while `connect()` is running. Late listeners will not receive events that already fired. Use the `on` or `addListener` methods before calling `connect()`: ```typescript theme={null} import { createClient, TruGenEvent } from "@trugen/js-sdk"; // Initialize client with your session token const session = await createClient({ token: sessionToken }); // Register listeners before starting the session session.on(TruGenEvent.CONNECTION_ESTABLISHED, () => { console.log("Connection Established"); }); session.on(TruGenEvent.TEXT_CHUNK_RECEIVED, (payload) => { console.log("Real-time transcript chunk:", payload.text); }); // Start connection await session.connect(); ``` *** ## Code Examples ### Connection Lifecycle ```typescript theme={null} import { TruGenEvent, ConnectionClosedCode } from "@trugen/js-sdk"; session.on(TruGenEvent.CONNECTION_CLOSED, (code: ConnectionClosedCode, reason: string) => { console.log(`Connection closed. Code: ${code}, Reason: ${reason}`); if (code === ConnectionClosedCode.MICROPHONE_PERMISSION_DENIED) { alert("Microphone permission was denied. Please check your browser settings."); } }); session.on(TruGenEvent.ERROR, (error) => { console.error("Session error:", error); }); ``` ### Rendering Video Stream ```typescript theme={null} session.on(TruGenEvent.VIDEO_STREAM_STARTED, (track) => { const videoElement = document.getElementById("avatarVideo"); track.attach(videoElement); }); ``` ### Custom Speaking/Listening Indicators ```typescript theme={null} session.on(TruGenEvent.USER_SPEECH_STARTED, () => { // Highlight user mic icon or show "Listening..." setListeningIndicator(true); }); session.on(TruGenEvent.USER_SPEECH_ENDED, () => { setListeningIndicator(false); }); session.on(TruGenEvent.AGENT_SPEAKING_STARTED, () => { // Show visual wave indicator for avatar speech setAvatarSpeaking(true); }); session.on(TruGenEvent.AGENT_SPEAKING_ENDED, () => { setAvatarSpeaking(false); }); ``` # List all events Source: https://docs.trugen.ai/docs/sdks/javascript/reference/list-all-events Reference guide for all supported TruGen JS SDK events. Here is the complete reference of all events emitted by the TruGen client session: Fired when the session connection state changes (e.g., to `CONNECTED`, `DISCONNECTED`). Fired when the WebRTC connection is successfully established. Fired when the session connection is terminated. Fired when the remote video track from the avatar becomes available. Fired when the remote audio track from the avatar becomes available. Fired when the client microphone input stream is initialized. Fired when the avatar starts speaking. Fired when the avatar finishes speaking. Fired when the user starts speaking. Useful for showing an active speaking or listening indicator in the UI. Fired when the user finishes speaking. Fired when the user interrupts the avatar's speech. Fired when real-time transcription/captions chunks are received. Fired when the browser is requesting microphone permissions. Fired when microphone permissions are granted. Fired when microphone permissions are denied by the user or browser. Fired when the active input audio capture device is changed. Fired when any WebRTC or connection errors occur. # Authentication Source: https://docs.trugen.ai/docs/sdks/python/authentication Secure your API keys and manage session tokens. TruGen AI uses a two-tier authentication system: **API keys** for server-side requests and **session tokens** for client-side connections. ## Tier 1: API Key Your API key authenticates server-side requests to the TruGen AI API. API keys can be created and managed from the [TruGen AI Dashboard](https://app.trugen.ai/). ### Creating an API Key From the [API Keys page](https://app.trugen.ai/api-keys), click **Create API Key**, give it a name, and click **Create**. Copy and store it securely: you will not be able to view it again. Never expose your API key in a client bundle, script shipped to end users, or public repository. Store it only in server-side environment variables or a secrets manager. If you lose your API key, you will need to create a new one: they cannot be recovered. ## Tier 2: Session Tokens Session tokens are temporary JWT credentials (valid for 5 minutes) that let clients connect to TruGen's streaming infrastructure without exposing your API key. ### How session tokens work Your server requests a session token from TruGen using your API key and agent ID. TruGen generates a temporary JWT tied to that specific agent configuration. Your Python client uses the session token to establish the WebRTC connection. Once connected, the client streams video/audio and receives events. ## Development vs. production There are two accepted patterns depending on where your Python code runs. ### Development / trusted environment For local development, backend jobs, and any environment that already trusts the machine, pass your API key directly to `TruGenClient`. The SDK handles the token exchange internally on every `create_session()` call. ```python theme={null} import os from trugen import TruGenClient client = TruGenClient(api_key=os.getenv("TRUGEN_API_KEY", "")) session = await client.create_session(agent_id=os.getenv("TRUGEN_AGENT_ID", "")) await session.connect() ``` This is the pattern used in the [Quickstart](/docs/sdks/python/quickstart) and the shipped example scripts. ### Production / shipped desktop apps If you're shipping a Python desktop application to end users (Windows/Mac/Linux binaries), do **not** embed your API key in the binary. Instead: 1. Run a small server-side endpoint that holds the API key. 2. Have your desktop app request a short-lived session token from your server. 3. Use the token to authenticate: see [Usage in Production](/docs/sdks/python/production) for the full pattern. ## Environment configuration Set your credentials in a `.env` file (loaded via `python-dotenv`) or export them directly: ```bash theme={null} export TRUGEN_API_KEY="your-api-key" export TRUGEN_AGENT_ID="your-agent-id" ``` ```python theme={null} from dotenv import load_dotenv import os load_dotenv() api_key = os.getenv("TRUGEN_API_KEY", "") agent_id = os.getenv("TRUGEN_AGENT_ID", "") ``` ## Next steps Ship desktop apps securely with server-side session tokens. Full SDK reference for initializing, streaming, and disconnecting. # Advanced GUI Example Source: https://docs.trugen.ai/docs/sdks/python/examples/advanced-python Full-feature TruGen SDK demo: captions, speaking states, connection quality, mic permissions, reconnect handling, and WAV audio injection. Every SDK feature in one runnable example. Adapted verbatim from `examples/advanced_session_ui.py` in the [official Python SDK repository](https://github.com/trugenai/python-sdk). ## Features demonstrated * Live video avatar display * Audio output with Acoustic Echo Cancellation (AEC) * Agent captions overlay * Mic mute/unmute * Agent speaking detection * User speaking detection * Connection quality monitoring * Mic permission events (pending / granted / denied) * Reconnect handling * **Custom WAV audio injection** (press **A** or pass `--wav` flag) * Input audio stream events ## Controls Click the video window first to focus it, then: | Key | Action | | - | - | | **M** | Toggle mic mute / unmute | | **A** | Inject WAV audio (requires `--wav` flag at launch) | | **Q** / **Esc** | Close window and quit | ## Requirements ```bash theme={null} uv add trugen-sdk --extra display # or: pip install trugen-sdk[display] # or: pip install opencv-python sounddevice numpy python-dotenv ``` Set your credentials in a `.env`: ```bash theme={null} TRUGEN_API_KEY=your-api-key TRUGEN_AGENT_ID=your-agent-id ``` ## Run ```bash theme={null} # Basic (no WAV injection) uv run --extra display python examples/advanced_session_ui.py # With a WAV file ready to inject on 'A' key press uv run --extra display python examples/advanced_session_ui.py --wav /path/to/audio.wav ``` ## Full source ```python theme={null} """ TruGen Advanced Avatar Viewer: Full SDK Features ================================================== Demonstrates every available TruGen SDK feature in one example. """ import os import sys import time import asyncio import textwrap import numpy as np import cv2 from dotenv import load_dotenv from trugen import TruGenClient, TruGenRunner, TruGenState, TruGenEvent load_dotenv() # ── Config ──────────────────────────────────────────────────────────────────── _wav_idx = sys.argv.index("--wav") + 1 if "--wav" in sys.argv else None WAV_FILE = sys.argv[_wav_idx] if _wav_idx and _wav_idx < len(sys.argv) else None WINDOW_TITLE = "TruGen AI: Full SDK Demo" FRAME_W, FRAME_H = 1280, 720 CAPTION_MAX_CHARS = 80 CAPTION_HOLD_SECS = 5.0 FONT = cv2.FONT_HERSHEY_DUPLEX FONT_SCALE = 0.60 FONT_THICK = 1 C_WHITE = (255, 255, 255) C_BLACK = (0, 0, 0) C_GREEN = (80, 200, 80) C_RED = (60, 60, 220) C_YELLOW = (0, 220, 220) C_GRAY = (180, 180, 180) C_BLUE = (220, 130, 60) C_OVERLAY = (20, 20, 20) # ── Runtime state (main-thread only: no lock needed) ───────────────────────── agent_speaking = False user_speaking = False audio_injecting = False conn_quality = ": " # ── GUI helpers ─────────────────────────────────────────────────────────────── def _overlay_rect(frame, x1, y1, x2, y2, color=C_OVERLAY, alpha=0.55): roi = frame[y1:y2, x1:x2] cv2.addWeighted(np.full_like(roi, color), alpha, roi, 1 - alpha, 0, roi) frame[y1:y2, x1:x2] = roi def _put_text(frame, text, x, y, color=C_WHITE, scale=FONT_SCALE, thick=FONT_THICK): cv2.putText(frame, text, (x, y), FONT, scale, C_BLACK, thick + 1, cv2.LINE_AA) cv2.putText(frame, text, (x, y), FONT, scale, color, thick, cv2.LINE_AA) def _placeholder() -> np.ndarray: frame = np.zeros((FRAME_H, FRAME_W, 3), dtype=np.uint8) msg = "Waiting for video avatar…" tw, th = cv2.getTextSize(msg, FONT, 0.9, 2)[0] cv2.putText(frame, msg, ((FRAME_W - tw) // 2, (FRAME_H + th) // 2), FONT, 0.9, C_GRAY, 2, cv2.LINE_AA) return frame # ── Session factory ─────────────────────────────────────────────────────────── async def create_session(): """Creates, connects, and returns a TruGenSession.""" client = TruGenClient(api_key=os.getenv("TRUGEN_API_KEY", "")) session = await client.create_session(agent_id=os.getenv("TRUGEN_AGENT_ID", "")) await session.connect() await session.enable_audio_output() # AEC + speaker output in one call return session # ── Runner ──────────────────────────────────────────────────────────────────── runner = TruGenRunner(session_factory=create_session) cv2.namedWindow(WINDOW_TITLE, cv2.WINDOW_NORMAL) cv2.resizeWindow(WINDOW_TITLE, FRAME_W, FRAME_H) # ── Event handlers ──────────────────────────────────────────────────────────── @runner.on_state def on_state(state: TruGenState) -> None: pass # Buffer streaming tokens for the caption overlay _caption_buffer: str = "" @runner.on_caption def on_caption(text: str) -> None: global _caption_buffer _caption_buffer = text # drives the GUI caption overlay # Terminal transcript logs: final, complete utterances only @runner.on_event("user.transcription_received") def on_user_transcript(text: str) -> None: print(f"[User] {text}") @runner.on_event("agent.transcription_final") def on_agent_transcript(text: str) -> None: print(f"[Agent] {text}") # Microphone permission lifecycle @runner.on_event(TruGenEvent.MIC_PERMISSION_PENDING) def on_mic_pending() -> None: pass @runner.on_event(TruGenEvent.MIC_PERMISSION_GRANTED) def on_mic_granted() -> None: pass @runner.on_event(TruGenEvent.MIC_PERMISSION_DENIED) def on_mic_denied() -> None: pass @runner.on_event(TruGenEvent.INPUT_AUDIO_STREAM_STARTED) def on_input_audio() -> None: pass # Agent speaking state @runner.on_event(TruGenEvent.AGENT_SPEAKING_STARTED) def on_agent_speak_start() -> None: global agent_speaking agent_speaking = True @runner.on_event(TruGenEvent.AGENT_SPEAKING_ENDED) def on_agent_speak_end() -> None: global agent_speaking, _caption_buffer agent_speaking = False _caption_buffer = "" # User speaking state @runner.on_event(TruGenEvent.USER_SPEECH_STARTED) def on_user_speak_start() -> None: global user_speaking user_speaking = True @runner.on_event(TruGenEvent.USER_SPEECH_ENDED) def on_user_speak_end() -> None: global user_speaking user_speaking = False # Connection resilience @runner.on_event("connection.reconnecting") def on_reconnecting() -> None: pass @runner.on_event("connection.reconnected") def on_reconnected() -> None: pass @runner.on_event("connection.quality_changed") def on_quality(participant, quality) -> None: global conn_quality conn_quality = str(quality).split(".")[-1] # ── WAV audio injection ─────────────────────────────────────────────────────── def inject_wav() -> None: """ Schedules WAV injection into the session. Auto-mutes the mic before injection and restores it after. This prevents AEC breakdown: without muting, the agent's response to the WAV audio loops back through the mic and floods the STT pipeline. """ global audio_injecting if not WAV_FILE: print("[Audio] ⚠️ No WAV file: pass --wav /path/to/file.wav") return if not os.path.isfile(WAV_FILE): print(f"[Audio] ❌ File not found: {WAV_FILE}") return session = runner.session if session is None: print("[Audio] ❌ Session not ready yet") return async def _do_inject(): global audio_injecting audio_injecting = True was_muted = runner.mic_muted if not was_muted: session.mute_input_audio() runner._shared.set_mic_muted(True) print("[Audio] 🔇 Mic muted for injection") print(f"[Audio] 🎵 Injecting: {os.path.basename(WAV_FILE)}") try: await session.upload_audio(WAV_FILE) print("[Audio] ✅ Injection complete") except Exception as exc: print(f"[Audio] ❌ Error: {exc}") finally: audio_injecting = False if not was_muted: session.unmute_input_audio() runner._shared.set_mic_muted(False) print("[Audio] 🎤 Mic restored") loop = runner._loop if loop and loop.is_running(): asyncio.run_coroutine_threadsafe(_do_inject(), loop) # ── Frame handler ───────────────────────────────────────────────────────────── @runner.on_frame def on_frame(frame: np.ndarray | None) -> None: display = frame.copy() if frame is not None else _placeholder() h, w = display.shape[:2] # Top status bar _overlay_rect(display, 0, 0, w, 36) # Left: session state state_color = C_GREEN if runner.session_state == TruGenState.CONNECTED else C_YELLOW _put_text(display, f" {runner.session_state.value}", 10, 23, color=state_color, scale=0.52) # Right: mic status mic_txt = "🔇 MUTED [M]" if runner.mic_muted else "🎤 ON [M]" mic_color = C_RED if runner.mic_muted else C_GREEN _put_text(display, mic_txt, w - 180, 23, color=mic_color, scale=0.48) # Audio injection banner if audio_injecting: _overlay_rect(display, 0, 36, w, 60) _put_text(display, f"🎵 Injecting: {os.path.basename(WAV_FILE or '')}", 10, 53, color=C_BLUE, scale=0.50) # Captions overlay caption, caption_ts = runner.get_caption() if caption and time.monotonic() - caption_ts < CAPTION_HOLD_SECS: lines = textwrap.wrap(caption, width=CAPTION_MAX_CHARS) line_h = 28 y0 = h - (len(lines) * line_h + 16) - 10 _overlay_rect(display, 0, y0, w, h - 10) for i, line in enumerate(lines): tw = cv2.getTextSize(line, FONT, FONT_SCALE, FONT_THICK)[0][0] _put_text(display, line, (w - tw) // 2, y0 + 20 + i * line_h) # Key hint bar at bottom: reminds user to focus the window hint = "Click this window first, then: M=mute A=inject WAV Q=quit" _put_text(display, hint, 10, h - 10, color=C_GRAY, scale=0.40) # Render cv2.imshow(WINDOW_TITLE, display) key = cv2.waitKey(1) & 0xFF if key in (ord("q"), ord("Q"), 27): runner.stop() elif key in (ord("m"), ord("M")): runner.toggle_mute() elif key in (ord("a"), ord("A")): inject_wav() if cv2.getWindowProperty(WINDOW_TITLE, cv2.WND_PROP_VISIBLE) < 1: runner.stop() # ── Main ────────────────────────────────────────────────────────────────────── if __name__ == "__main__": wav_hint = f"WAV loaded: {WAV_FILE}" if WAV_FILE else "pass --wav /path/to/file.wav to enable audio injection" print(f"Controls: M = mute | A = inject WAV | Q = quit (click the video window first)") print(f"Audio: {wav_hint}\n") runner.run() cv2.destroyAllWindows() ``` ## Notable patterns to steal * **`inject_wav()`** schedules audio injection safely using `asyncio.run_coroutine_threadsafe`: the correct way to bridge from your main GUI thread into the SDK's async loop. * **Mic muting during injection**: this is critical for AEC. Without it, the agent responds to its own injected audio via the mic, spiraling into feedback. * **`connection.quality_changed`** gives you a live signal from LiveKit about the participant's connection quality: display it as a small badge for user awareness. * **`_caption_buffer`** on `TEXT_CHUNK_RECEIVED` is cleared when the agent stops speaking, so stale captions don't linger. ## Next steps The minimal viewer this one is built on. Deeper reference on injection and mic control. # Basic GUI Example Source: https://docs.trugen.ai/docs/sdks/python/examples/basic-python Complete OpenCV viewer with connection status bar, mic mute indicator, and floating captions. A minimal but production-shaped OpenCV viewer for a TruGen agent. Adapted verbatim from the `examples/basic_session_ui.py` in the [official Python SDK repository](https://github.com/trugenai/python-sdk). ## What it does * Connects to a live TruGen session and renders the avatar in a resizable OpenCV window * Shows a top status bar with the current session state and mic status * Overlays streaming captions with a fade-out timer at the bottom * Toggles mic mute with **M**, quits with **Q** or **Esc** ## Requirements ```bash theme={null} uv add trugen-sdk --extra display # or: pip install trugen-sdk[display] # or: pip install opencv-python sounddevice numpy python-dotenv ``` Set your credentials in a `.env`: ```bash theme={null} TRUGEN_API_KEY=your-api-key TRUGEN_AGENT_ID=your-agent-id ``` ## Run ```bash theme={null} uv run --extra display python examples/basic_session_ui.py ``` ## Full source ```python theme={null} """ TruGen Interactive Avatar Viewer ================================= Connects to a TruGen AI session and displays the live video avatar in a GUI window. Controls: M / m: Toggle mic mute/unmute Q / Esc: Close window and quit """ import os import time import textwrap import numpy as np import cv2 from dotenv import load_dotenv from trugen import TruGenClient, TruGenRunner, TruGenState, TruGenEvent load_dotenv() # ── Display settings ─────────────────────────────────────────────────────────── WINDOW_TITLE = "TruGen AI: Live Avatar" FRAME_W, FRAME_H = 1280, 720 CAPTION_MAX_CHARS = 80 CAPTION_HOLD_SECS = 5.0 FONT = cv2.FONT_HERSHEY_DUPLEX FONT_SCALE = 0.65 FONT_THICK = 1 C_WHITE = (255, 255, 255) C_BLACK = (0, 0, 0) C_GREEN = (80, 200, 80) C_RED = (60, 60, 220) C_YELLOW = (0, 220, 220) C_GRAY = (180, 180, 180) C_OVERLAY = (20, 20, 20) # ── GUI helpers ──────────────────────────────────────────────────────────────── def _overlay_rect(frame, x1, y1, x2, y2, color=C_OVERLAY, alpha=0.55): roi = frame[y1:y2, x1:x2] cv2.addWeighted(np.full_like(roi, color), alpha, roi, 1 - alpha, 0, roi) frame[y1:y2, x1:x2] = roi def _put_text(frame, text, x, y, color=C_WHITE, scale=FONT_SCALE, thick=FONT_THICK): cv2.putText(frame, text, (x, y), FONT, scale, C_BLACK, thick + 1, cv2.LINE_AA) cv2.putText(frame, text, (x, y), FONT, scale, color, thick, cv2.LINE_AA) def _placeholder() -> np.ndarray: frame = np.zeros((FRAME_H, FRAME_W, 3), dtype=np.uint8) msg = "Waiting for video avatar…" tw, th = cv2.getTextSize(msg, FONT, 0.9, 2)[0] cv2.putText(frame, msg, ((FRAME_W - tw) // 2, (FRAME_H + th) // 2), FONT, 0.9, C_GRAY, 2, cv2.LINE_AA) return frame # ── Session factory: user owns TruGenClient and session creation ────────────── async def create_session(): """Creates, connects, and returns a TruGenSession.""" client = TruGenClient(api_key=os.getenv("TRUGEN_API_KEY", "")) session = await client.create_session(agent_id=os.getenv("TRUGEN_AGENT_ID", "")) await session.connect() await session.enable_audio_output() # AEC + speaker output return session # ── Runner setup ─────────────────────────────────────────────────────────────── runner = TruGenRunner(session_factory=create_session) cv2.namedWindow(WINDOW_TITLE, cv2.WINDOW_NORMAL) cv2.resizeWindow(WINDOW_TITLE, FRAME_W, FRAME_H) @runner.on_state def on_state(state: TruGenState) -> None: pass @runner.on_event(TruGenEvent.AGENT_SPEAKING_STARTED) def on_speak_start() -> None: pass @runner.on_event(TruGenEvent.AGENT_SPEAKING_ENDED) def on_speak_end() -> None: pass @runner.on_frame def on_frame(frame: np.ndarray | None) -> None: display = frame.copy() if frame is not None else _placeholder() h, w = display.shape[:2] # Status bar _overlay_rect(display, 0, 0, w, 34) state_color = C_GREEN if runner.session_state == TruGenState.CONNECTED else C_YELLOW _put_text(display, f" {runner.session_state.value}", 10, 22, color=state_color, scale=0.58) mic_text = "🔇 MIC MUTED [M to unmute]" if runner.mic_muted else "🎤 MIC ON [M to mute]" mic_color = C_RED if runner.mic_muted else C_GREEN _put_text(display, mic_text, w - 280, 22, color=mic_color, scale=0.55) _put_text(display, "Q / Esc: quit", w // 2 - 55, 22, color=C_GRAY, scale=0.50) # Captions caption, caption_ts = runner.get_caption() if caption and time.monotonic() - caption_ts < CAPTION_HOLD_SECS: lines = textwrap.wrap(caption, width=CAPTION_MAX_CHARS) line_h = 28 y0 = h - (len(lines) * line_h + 16) - 10 _overlay_rect(display, 0, y0, w, h - 10) for i, line in enumerate(lines): tw = cv2.getTextSize(line, FONT, FONT_SCALE, FONT_THICK)[0][0] _put_text(display, line, (w - tw) // 2, y0 + 20 + i * line_h) # Render & key handling cv2.imshow(WINDOW_TITLE, display) key = cv2.waitKey(1) & 0xFF if key in (ord("q"), ord("Q"), 27): runner.stop() elif key in (ord("m"), ord("M")): runner.toggle_mute() if cv2.getWindowProperty(WINDOW_TITLE, cv2.WND_PROP_VISIBLE) < 1: runner.stop() # ── Main ─────────────────────────────────────────────────────────────────────── if __name__ == "__main__": print("Controls: M = mute/unmute | Q / Esc = quit\n") runner.run() cv2.destroyAllWindows() ``` ## What to notice * **`create_session()`** owns the connection: this pattern keeps your credentials, agent selection, and setup calls in one place. * **`enable_audio_output()`** activates the speaker with Acoustic Echo Cancellation. Without it, the agent hears its own voice through the mic and gets caught in a feedback loop. * **`@runner.on_frame`** runs on the main thread, so `cv2.imshow`, `cv2.waitKey`, and window management are all safe from here. * **`runner.get_caption()`** returns `(text, timestamp)` so you can time-box overlays: the `CAPTION_HOLD_SECS` check fades captions after 5 seconds. * **`runner.stop()`** is thread-safe and idempotent: call it from any thread, any time. ## Next steps Full-feature viewer with WAV injection, speaking indicators, and reconnect handling. Subscribe to every event the SDK emits. # Python SDK Source: https://docs.trugen.ai/docs/sdks/python/overview Official Python SDK for TruGen AI: real-time avatar streaming for desktop, GUI, and backend applications. The **TruGen AI Python SDK** (`trugen-sdk`) is the official Python client for building real-time avatar experiences in Python. Everything WebRTC- and audio-related (LiveKit transport, Acoustic Echo Cancellation, decoding, threading) is handled under the hood. You only ever import from `trugen`. ## When to use it * **Desktop and GUI applications**: OpenCV, Pygame, PyQt/PySide, or custom game engines * **Backend orchestration**: spin up sessions from Python workers, cron jobs, or queue consumers * **Audio injection pipelines**: pump pre-recorded WAV or raw PCM into a live agent conversation * **Automation & data workflows**: connect avatar sessions to your existing Python stack If you're building a browser-facing UI, use the [JavaScript SDK](/docs/sdks/javascript/overview) instead. ## What the SDK provides * 🎥 **Real-time audio/video streaming**: synchronised high-quality frames from the avatar * 🔇 **Built-in Acoustic Echo Cancellation**: one call to `enable_audio_output()` handles APM sync so the avatar never hears itself * 🟩 **BGR OpenCV frames**: zero-boilerplate async iterator yielding pre-converted NumPy arrays * ⚙️ **GUI runner support**: thread-safe `TruGenRunner` wrapper for blocking rendering loops * 🎵 **Custom audio injection**: inject WAV files or raw 16-bit PCM directly into the room * 🎙️ **Microphone lifecycle management**: mute/unmute, permission monitoring, device control * 💬 **Real-time captions**: event hooks for streaming caption chunks and final transcripts * 📡 **Async iterator API**: stream raw audio and video natively via async generators * 🎯 **Event-driven architecture**: decorator-based handlers for connection, tracks, and speech events * 📝 **Fully typed**: complete type hints for IDE autocompletion and safety ## Requirements * **Python 3.10+** * **Core dependencies** (installed automatically): * `livekit` (>= 0.11.0) * `aiohttp` (>= 3.8.0) * **Optional `[display]` extras** (for GUI examples): * `opencv-python` (>= 4.8.0) * `sounddevice` (>= 0.4.6) * `numpy` (>= 1.24.0) ## Installation ```bash theme={null} # Using uv (recommended) uv add trugen-sdk # With optional display utilities (OpenCV, audio playback) uv add trugen-sdk --extra display # Using pip pip install trugen-sdk # With optional display utilities pip install trugen-sdk[display] ``` ## Package exports Everything you need is re-exported from the top-level `trugen` package: ```python theme={null} from trugen import TruGenClient, TruGenSession, TruGenRunner, TruGenState, TruGenEvent ``` ## Next steps Stream your first avatar in a Python GUI in under 5 minutes. Secure your API key and manage session tokens. # Usage in Production Source: https://docs.trugen.ai/docs/sdks/python/production Securely deploy TruGen AI in production Python environments. For any Python application shipped to end users (desktop binaries, packaged distributions, or apps you don't fully control), do not embed your API key. Follow the two-step pattern below: 1. Exchange your API key for a short-lived session token **on the server side**. 2. Return the token to the client and use it in place of the API key. ## Getting a Session Token Session tokens are valid for 5 minutes by default. Request a new token per user session rather than caching them long-term. The session token endpoint must be called from your server, not from your desktop app. Making this request from a shipped binary would expose your API key. ### Fetching a Session Token on Your Server From your server (Python, Node, Go: anything), call TruGen's `/v1/auth/conversation` endpoint with your API key and the target agent ID. ```python server.py (FastAPI) theme={null} import os import httpx from fastapi import FastAPI, HTTPException from pydantic import BaseModel app = FastAPI() class TokenRequest(BaseModel): agentId: str userName: str | None = None userId: str | None = None @app.post("/api/session-token") async def create_session_token(req: TokenRequest): async with httpx.AsyncClient() as client: r = await client.post( "https://api.trugen.ai/v1/auth/conversation", headers={"X-API-Key": os.environ["TRUGEN_API_KEY"]}, json=req.model_dump(exclude_none=True), ) if r.status_code != 200: raise HTTPException(r.status_code, r.text) return r.json() ``` ```python server.py (Flask) theme={null} import os import httpx from flask import Flask, request, jsonify app = Flask(__name__) @app.route("/api/session-token", methods=["POST"]) def create_session_token(): payload = request.get_json() with httpx.Client() as client: r = client.post( "https://api.trugen.ai/v1/auth/conversation", headers={"X-API-Key": os.environ["TRUGEN_API_KEY"]}, json={ "agentId": payload["agentId"], "userName": payload.get("userName"), "userId": payload.get("userId"), }, ) return jsonify(r.json()), r.status_code ``` The response contains a `token` field, plus the `conversationId`, the LiveKit `url`, and the avatar metadata. ## Using the Token in Your Desktop App Once your app receives the token from your backend, use it in place of a `create_session()` call by connecting to LiveKit with the returned token/URL directly. The Python SDK's `TruGenClient.create_session()` currently expects an API key. For a token-based flow in Python, contact [support@trugen.ai](mailto:support@trugen.ai) for the recommended pattern for your deployment shape. ## User Identity Configuration When generating a session token, you can optionally supply details about the user connecting: * **`userName`**: Display name (defaults to `"JS SDK"` if omitted; safe to override). * **`userId`**: Unique user identifier. If omitted, TruGen auto-generates a timestamp-based ID. These are included in the JSON body sent to `https://api.trugen.ai/v1/auth/conversation`. ### Example Request Body ```json theme={null} { "agentId": "your-agent-id-here", "userName": "Alice Smith", "userId": "user_alice_123" } ``` ## Common Error Responses | Status Code | Meaning | Solution | | :- | :- | :- | | **400** | Invalid request body or malformed `agentId` | Check your JSON shape and verify the agent ID is a valid UUID | | **401** | Invalid, missing, or expired API key | Verify your API key and its inclusion in the `X-API-Key` header | | **500** | Agent not found or database error | Confirm the agent exists and belongs to your account | ## Next steps Full two-tier authentication overview. Full SDK reference for initializing, streaming, and disconnecting. # Quickstart Source: https://docs.trugen.ai/docs/sdks/python/quickstart Stream your first TruGen avatar in a Python OpenCV window in under 5 minutes. This quickstart uses `TruGenRunner`: the thread-safe wrapper that runs the async session loop on a background thread while your main thread handles rendering. Perfect for OpenCV, Pygame, PyQt/PySide, or any UI toolkit. ## Prerequisites * **Python 3.10+** * A TruGen API key from the [Developer Portal](https://app.trugen.ai) * An agent ID: create one in the [Teammate Library](https://app.trugen.ai/teammate-library) ## 1. Install ```bash theme={null} uv add trugen-sdk --extra display # or: pip install trugen-sdk[display] ``` The `[display]` extra pulls in `opencv-python`, `sounddevice`, and `numpy` for the GUI example below. ## 2. Set your credentials Create a `.env` file: ```bash theme={null} TRUGEN_API_KEY=your-api-key TRUGEN_AGENT_ID=your-agent-id ``` ## 3. Run your first avatar Save the following as `avatar.py`: ```python theme={null} import cv2 import os from trugen import TruGenClient, TruGenRunner # 1. Define how to connect to the session async def create_session(): client = TruGenClient(api_key=os.getenv("TRUGEN_API_KEY", "")) session = await client.create_session(agent_id=os.getenv("TRUGEN_AGENT_ID", "")) await session.connect() await session.enable_audio_output() # Speaker + AEC in one call return session # 2. Initialize the runner runner = TruGenRunner(session_factory=create_session) # 3. Handle incoming frames @runner.on_frame def show_frame(frame): if frame is not None: cv2.imshow("TruGen Avatar", frame) if cv2.waitKey(1) & 0xFF == ord('q'): runner.stop() # 4. Start rendering loop (blocks main thread) if __name__ == "__main__": runner.run() cv2.destroyAllWindows() ``` Run it: ```bash theme={null} uv run --extra display python avatar.py # or: python avatar.py ``` A window opens showing the avatar. Speak into your microphone: the agent responds. Press **Q** to quit. ## What just happened * **`create_session`** initialised a `TruGenClient` with your API key and asked it to create a `TruGenSession` for your agent. `connect()` opened the WebRTC connection; `enable_audio_output()` activated the speaker with built-in Acoustic Echo Cancellation. * **`TruGenRunner`** spun up a background thread running the async session event loop. The main thread stays free for your rendering code. * **`@runner.on_frame`** registered a callback that fires on the main thread with each new BGR video frame (a NumPy array): perfect for OpenCV, Pygame, or any UI toolkit. * **`runner.run()`** blocked the main thread to drive the rendering loop; `runner.stop()` (from the `q` key press) shut down the background loop and cleanly disconnected. ## Next steps Secure your API key and manage session tokens. Full SDK reference for initializing, streaming, and disconnecting. Complete OpenCV viewer with status bar, mic indicator, and floating captions. Listen to connection, speaking, and transcription events in real time. # Audio Control Source: https://docs.trugen.ai/docs/sdks/python/reference/audio-control Manage microphone lifecycle, mute states, and custom audio injection in the Python SDK. The Python SDK gives you programmatic control over the local microphone and lets you inject custom audio (WAV files or raw 16-bit PCM bytes) directly into the room. ## Microphone Management ### Start/Stop Microphone Programmatically connect or disconnect the microphone track: ```python theme={null} # Connect and publish the microphone track await session.start_mic() # Stop capturing and unpublish the microphone track await session.stop_mic() ``` ### Muting and Unmuting Mute or unmute microphone input without tearing down the audio track: ```python theme={null} # Mute the microphone session.mute_input_audio() # Unmute the microphone session.unmute_input_audio() # Check the current mute state if session.is_input_muted(): print("Mic is currently muted") ``` ### Get Microphone State `get_input_audio_state()` returns an `InputAudioState` object containing both the mute status and mic permission status: ```python theme={null} state = session.get_input_audio_state() print("Muted:", state.is_muted) print("Permission:", state.permission_state) # 'pending' | 'granted' | 'denied' ``` ### TruGenRunner shortcut If you're using `TruGenRunner`, toggle mute from the main thread safely: ```python theme={null} runner.toggle_mute() if runner.mic_muted: print("Currently muted") ``` ## Audio Injection You can stream custom audio into the room: a pre-recorded WAV file or raw 16-bit PCM bytes. Useful for scripted playback, voice cloning demos, or piping in audio from another source. Auto-mute the microphone before injecting audio, then unmute after it completes. Without muting, the agent's response to your injected audio loops back through the mic and floods the STT pipeline: see the WAV-injection helper in [`examples/advanced_session_ui.py`](/docs/sdks/python/examples/advanced-python) for the recommended pattern. ### Upload a WAV file Stream a PCM WAV file into the room: ```python theme={null} await session.upload_audio("/path/to/audio.wav") ``` The SDK handles reading, decoding, and pacing the audio into the session at the right sample rate. ### Send raw PCM bytes Inject raw 16-bit PCM bytes directly: ```python theme={null} await session.send_audio( data=pcm_bytes, # bytes-like object, 16-bit little-endian PCM sample_rate=48000, # default 48000 num_channels=1, # default 1 (mono) ) ``` Use `send_audio()` when your source is already decoded: TTS output from another provider, live audio from a different track, or synthetic audio you're generating on the fly. ### Safe injection pattern The recommended pattern (used in `examples/advanced_session_ui.py`) mutes the mic during injection and restores its previous state afterwards: ```python theme={null} async def inject_safely(session, runner, wav_path): was_muted = runner.mic_muted if not was_muted: session.mute_input_audio() try: await session.upload_audio(wav_path) finally: if not was_muted: session.unmute_input_audio() ``` ## Next steps Listen to connection, speaking, and transcription events. Full GUI viewer with WAV injection, captions, and speaking state. # Basic Usage Source: https://docs.trugen.ai/docs/sdks/python/reference/basic-usage Install, initialize, and manage the TruGen AI Python SDK. The core primitives of the Python SDK are `TruGenClient`, `TruGenSession`, and `TruGenRunner`. This page walks each one from bottom to top so you understand what's happening under the hood before adopting the higher-level `TruGenRunner` in your app. ## Installation ```bash theme={null} uv add trugen-sdk # or with GUI extras: uv add trugen-sdk --extra display # pip equivalent: pip install trugen-sdk[display] ``` ## Requirements * Python 3.10+ * **Core:** `livekit` (>= 0.11.0), `aiohttp` (>= 3.8.0) * **`[display]` extras:** `opencv-python` (>= 4.8.0), `sounddevice` (>= 0.4.6), `numpy` (>= 1.24.0) ## TruGenClient The entry point for starting TruGen AI sessions. ```python theme={null} from trugen import TruGenClient # Initialize with your API key client = TruGenClient(api_key="your-api-key") # Create a session with your Agent ID session = await client.create_session(agent_id="your-agent-id") ``` `create_session()` is `async`: call it from an event loop. ## TruGenSession Represents an active connection to a streaming room. Everything below is a method or attribute on the session returned from `create_session()`. ### Connection * `await session.connect()`: Connect to the streaming room and publish the local microphone. * `await session.disconnect()`: Disconnect and cleanly release all hardware/stream resources. ### Audio Output * `await session.enable_audio_output()`: Activates speaker playback with built-in echo cancellation. Call this once after `connect()`. ### Video & Audio Generators * `session.video_frames_bgr()`: Async generator yielding NumPy arrays (`NDArray`) in BGR format, ready for OpenCV. * `session.video_frames()`: Async generator yielding raw LiveKit `VideoFrame` objects. * `session.audio_frames()`: Async generator yielding raw LiveKit `AudioFrame` objects. ### Low-Level Accessors * `session.get_video_track()`: Returns the remote `RemoteVideoTrack` object (or `None`). * `session.get_audio_track()`: Returns the remote `RemoteAudioTrack` object (or `None`). * `session.room`: Returns the underlying `livekit.rtc.Room` instance for advanced operations. ## Direct session usage (async only) If you're already inside an event loop and don't need thread-safety, use the session directly with `async for`: ```python theme={null} import asyncio import cv2 import os from trugen import TruGenClient async def main(): client = TruGenClient(api_key=os.getenv("TRUGEN_API_KEY", "")) session = await client.create_session(agent_id=os.getenv("TRUGEN_AGENT_ID", "")) await session.connect() await session.enable_audio_output() async for frame in session.video_frames_bgr(): cv2.imshow("Avatar", frame) if cv2.waitKey(1) & 0xFF == ord("q"): break await session.disconnect() cv2.destroyAllWindows() if __name__ == "__main__": asyncio.run(main()) ``` This works but blocks the async loop on OpenCV's `imshow`. For real GUI apps, use `TruGenRunner` instead. ## TruGenRunner `TruGenRunner` handles the multi-threading dance for you: the async session event loop runs on a background thread while your main thread stays free to drive rendering (OpenCV, Pygame, PyQt/PySide, or any custom engine). ### Basic setup ```python theme={null} from trugen import TruGenClient, TruGenRunner async def create_session(): client = TruGenClient(api_key="…") session = await client.create_session(agent_id="…") await session.connect() await session.enable_audio_output() return session runner = TruGenRunner(session_factory=create_session) ``` ### Controls * `runner.run()`: Starts the runner and blocks the main thread to run the rendering loop. * `runner.stop()`: Safely stops the background loop and disconnects the session (thread-safe). * `runner.toggle_mute()`: Toggles the microphone mute state (thread-safe). ### Properties & Accessors * `runner.mic_muted`: Returns `True` if the microphone is currently muted. * `runner.session_state`: Returns the current session state enum (`TruGenState`). * `runner.session`: Access the active `TruGenSession` instance (returns `None` until connected). * `runner.get_caption()`: Returns a tuple `(text, timestamp)` containing the last received caption chunk and the monotonic timestamp it arrived. ### The frame callback Register a function to be called with every new BGR video frame on the main thread: ```python theme={null} @runner.on_frame def on_frame(frame): if frame is not None: cv2.imshow("Avatar", frame) if cv2.waitKey(1) & 0xFF == ord("q"): runner.stop() ``` The callback receives either a NumPy `ndarray` (a BGR frame) or `None` when no frame is currently available. ## Session states | Enum Value | Description | | - | - | | `TruGenState.INITIALIZING` | Session created but not yet connected | | `TruGenState.CONNECTING` | WebRTC handshake and connection in progress | | `TruGenState.CONNECTED` | Connection established; actively streaming media | | `TruGenState.DISCONNECTED` | Session ended and connection closed | | `TruGenState.ERROR` | Unrecoverable error occurred | Check the current state at any time: ```python theme={null} if runner.session_state == TruGenState.CONNECTED: print("Live!") ``` ## Error handling Wrap `create_session()` and `connect()` with standard try/except blocks: ```python theme={null} import asyncio from trugen import TruGenClient client = TruGenClient(api_key="invalid-key") async def main(): try: session = await client.create_session(agent_id="my-agent") await session.connect() except RuntimeError as e: print(f"Connection failed: {e}") except Exception as e: print(f"An unexpected error occurred: {e}") asyncio.run(main()) ``` For runtime errors during a live session, subscribe to `TruGenEvent.ERROR`: see [Event Handling](/docs/sdks/python/reference/event-handling). ## Next steps Microphone lifecycle, mute controls, and custom audio injection. Subscribe to connection, speaking, and transcription events. # Event Handling Source: https://docs.trugen.ai/docs/sdks/python/reference/event-handling Listen to real-time session, media, speech, and transcription events with decorator-based handlers. Every `TruGenSession` and `TruGenRunner` is event-driven. Register handlers with decorators; the SDK invokes them on the correct thread as events fire. You have two entry points: * **`@runner.on_*`** decorators on a `TruGenRunner`: main-thread callbacks, ideal for UI updates * **`@session.on()`** decorator on a `TruGenSession`: low-level async callbacks, run on the session's event loop Use runner decorators for GUI apps. Use session decorators when you're driving the session directly from your own async code. ## Runner Decorators ### `@runner.on_frame` Receives BGR video frames (NumPy arrays) or `None` on the main thread. Fired on every new frame. ```python theme={null} @runner.on_frame def on_frame(frame): if frame is not None: cv2.imshow("Avatar", frame) ``` ### `@runner.on_caption` Receives real-time streaming caption chunks: ideal for UI overlays. ```python theme={null} @runner.on_caption def on_caption(text: str): # Fired for each caption chunk as it arrives pass ``` ### `@runner.on_state` Called when the session's connection state transitions. ```python theme={null} from trugen import TruGenState @runner.on_state def on_state(state: TruGenState): print(f"Status: {state.value}") ``` ### `@runner.on_event` Handles any standard `TruGenEvent` enum or custom string event. ```python theme={null} from trugen import TruGenEvent # Log final complete transcripts @runner.on_event("user.transcription_received") def on_user_transcript(text: str): print(f"[User] {text}") @runner.on_event("agent.transcription_final") def on_agent_transcript(text: str): print(f"[Agent] {text}") # Handle speaking state changes @runner.on_event(TruGenEvent.AGENT_SPEAKING_STARTED) def on_speak_start(): print("Agent started speaking…") ``` ## Session Decorators If you're not using `TruGenRunner`, listen to events directly on the `TruGenSession` using `@session.on()`: ```python theme={null} from trugen import TruGenEvent # Final complete transcripts @session.on("user.transcription_received") def on_user_speech(text: str): print(f"[User] {text}") @session.on("agent.transcription_final") def on_agent_speech(text: str): print(f"[Agent] {text}") # Speaking state changes @session.on(TruGenEvent.AGENT_SPEAKING_STARTED) def agent_speech_start(): print("Agent started speaking...") ``` Register handlers before calling `session.connect()`. Startup events like microphone permission, connection, and stream initialization can fire while `connect()` is running. Late listeners will not receive events that already fired. ## Common patterns ### Connection lifecycle ```python theme={null} from trugen import TruGenState, TruGenEvent @runner.on_state def on_state(state: TruGenState): if state == TruGenState.CONNECTED: print("Live!") elif state == TruGenState.DISCONNECTED: print("Session ended.") elif state == TruGenState.ERROR: print("Something broke.") @runner.on_event(TruGenEvent.ERROR) def on_error(err): print(f"Session error: {err}") ``` ### Reconnection handling Transient network drops emit `connection.reconnecting` and `connection.reconnected` as string events: ```python theme={null} @runner.on_event("connection.reconnecting") def on_reconnecting(): print("Reconnecting…") @runner.on_event("connection.reconnected") def on_reconnected(): print("Back online.") ``` ### Speaking indicators ```python theme={null} from trugen import TruGenEvent agent_speaking = False user_speaking = False @runner.on_event(TruGenEvent.AGENT_SPEAKING_STARTED) def _agent_start(): global agent_speaking agent_speaking = True @runner.on_event(TruGenEvent.AGENT_SPEAKING_ENDED) def _agent_end(): global agent_speaking agent_speaking = False @runner.on_event(TruGenEvent.USER_SPEECH_STARTED) def _user_start(): global user_speaking user_speaking = True @runner.on_event(TruGenEvent.USER_SPEECH_ENDED) def _user_end(): global user_speaking user_speaking = False ``` ### Microphone permission lifecycle ```python theme={null} from trugen import TruGenEvent @runner.on_event(TruGenEvent.MIC_PERMISSION_PENDING) def on_mic_pending(): print("Waiting for microphone permission…") @runner.on_event(TruGenEvent.MIC_PERMISSION_GRANTED) def on_mic_granted(): print("Microphone granted.") @runner.on_event(TruGenEvent.MIC_PERMISSION_DENIED) def on_mic_denied(): print("Microphone denied: the agent won't hear the user.") ``` ## Next steps Complete reference of every event the SDK emits. Programmatically control the mic and inject audio. # List all events Source: https://docs.trugen.ai/docs/sdks/python/reference/list-all-events Complete reference of all events emitted by the TruGen Python SDK. Register listener callbacks on a `TruGenSession` via `@session.on()` or on a `TruGenRunner` via `@runner.on_event()`. Both accept either a `TruGenEvent` enum value or a string event name. ## Enum-based events (`TruGenEvent`) Fired when the session state changes (e.g., to `CONNECTED`, `DISCONNECTED`). Fired when the WebRTC connection is successfully established. Fired when the session room disconnects. Fired when the remote video track from the avatar is subscribed. Fired when the remote audio track from the avatar is subscribed. Fired when the local microphone audio stream begins publishing. Fired when the avatar starts speaking. Fired when the avatar stops speaking. Fired when the user starts speaking. Useful for showing an active listening indicator. Fired when the user finishes speaking. Fired when a real-time transcription / caption chunk is received. Fired when microphone permission is being requested. Fired when microphone permission has been granted. Fired when microphone permission has been denied. Fired when a session or connection error occurs. ## String-based events Some events don't have a dedicated enum entry: subscribe by string name instead. Fired when the user completes a final utterance (the fully committed transcript, not a streaming chunk). Fired when the agent completes a final utterance. Use alongside `TEXT_CHUNK_RECEIVED` for streaming captions plus finalized transcripts. Fired when a transient network reconnection begins. Fired when a network reconnection completes. Fired when a participant's connection quality changes. ## Runner-only decorators These fire on the main thread and are only available on `TruGenRunner`: Called with each new BGR video frame (a NumPy array) or `None` when no frame is currently available. Called with each streaming caption chunk as it arrives. Called on every session state transition. ## Session states (`TruGenState`) | Enum Value | Description | | - | - | | `TruGenState.INITIALIZING` | Session created but not yet connected | | `TruGenState.CONNECTING` | WebRTC handshake and connection in progress | | `TruGenState.CONNECTED` | Connection established; actively streaming media | | `TruGenState.DISCONNECTED` | Session ended and connection closed | | `TruGenState.ERROR` | Unrecoverable error occurred | # Livekit Integration Source: https://docs.trugen.ai/docs/voice-to-video/livekit Give a face to your LiveKit agents with TruGen Avatars, using our official LiveKit Agents plugin. Give a face to your LiveKit agents with TruGen Avatars, using our official LiveKit Agents plugin. Install the latest version of the TruGen plugin from the LiveKit registry: ```bash theme={null} uv add "livekit-agents[trugen]" # When using UV ``` ```bash theme={null} pip install -U "livekit-agents[trugen]" # When using PIP ``` 1. Using the TruGen [Developer Platform](https://app.trugen.ai), generate an API key from the developers page. 2. Set the newly generated API key as `TRUGEN_API_KEY` environment variable in your `.env` file. 1. Import the `trugen` plugin from `livekit.plugins`: ```python theme={null} from livekit.plugins import trugen ``` 2. Instantiate a new `AvatarSession` and set the avatar ID: ```python theme={null} avatar_id = os.getenv("TRUGEN_AVATAR_ID") or "45e3f732" trugen_avatar = trugen.AvatarSession(avatar_id=avatar_id) ``` 3. Start the avatar session, passing the current agent session and room context: ```python theme={null} await trugen_avatar.start(session, room=ctx.room) ``` #### Complete Example ```python Python highlight={1-2,8-10} theme={null} from livekit.plugins import trugen async def entrypoint(ctx: JobContext): session = AgentSession( # Your existing configuration ) avatar_id = os.getenv("TRUGEN_AVATAR_ID") or "45e3f732" trugen_avatar = trugen.AvatarSession(avatar_id=avatar_id) await trugen_avatar.start(session, room=ctx.room) await session.start( # Start agent session as usual ) ``` 4. To gracefully shut down, use `ctx.room.disconnect()` to close the room connection or `ctx.shutdown()` to end the `JobContext`. TruGen automatically stops the session when the room is disconnected or the primary participant disconnects. Install the latest version of the TruGen plugin: ```bash npm theme={null} npm install @livekit/agents-plugin-trugen@latest ``` ```bash pnpm theme={null} pnpm add @livekit/agents-plugin-trugen@latest ``` Add the following to your `.env` file: ```ini .env theme={null} TRUGEN_API_KEY=your-trugen-api-key TRUGEN_AVATAR_ID=your-avatar-id LIVEKIT_URL=your-livekit-url LIVEKIT_API_KEY=your-livekit-api-key LIVEKIT_API_SECRET=your-livekit-api-secret ``` ```typescript TypeScript theme={null} import { AvatarSession } from '@livekit/agents-plugin-trugen'; const avatarSession = new AvatarSession({ avatarId: process.env.TRUGEN_AVATAR_ID, apiKey: process.env.TRUGEN_API_KEY, }); await avatarSession.start(agentSession, room, { livekitUrl: process.env.LIVEKIT_URL, livekitApiKey: process.env.LIVEKIT_API_KEY, livekitApiSecret: process.env.LIVEKIT_API_SECRET, }); ``` ```javascript JavaScript theme={null} import { AvatarSession } from '@livekit/agents-plugin-trugen'; const avatarSession = new AvatarSession({ avatarId: process.env.TRUGEN_AVATAR_ID, apiKey: process.env.TRUGEN_API_KEY, }); await avatarSession.start(agentSession, room, { livekitUrl: process.env.LIVEKIT_URL, livekitApiKey: process.env.LIVEKIT_API_KEY, livekitApiSecret: process.env.LIVEKIT_API_SECRET, }); ``` | Option | Required | Default | Description | | - | - | - | - | | `apiKey` | Yes | : | Your TruGen API key | | `avatarId` | No | Stock avatar | The avatar ID to use | | `apiUrl` | No | `https://api.trugen.ai` | TruGen API base URL | | `avatarParticipantIdentity` | No | `trugen-avatar` | LiveKit participant identity | | `avatarParticipantName` | No | `Trugen Avatar` | Display name in the room | | `connOptions` | No | : | Connection retry configuration | ## More Resources Explore the full list of ready-to-use avatars. Official GitHub examples for LiveKit + TruGen. Explore LiveKit Agent plugin examples. Explore the full LiveKit documentation.