diff --git a/.claude/rules/mdx-diagrams.md b/.claude/rules/mdx-diagrams.md index de4cd2bd1d..63476c5f5f 100644 --- a/.claude/rules/mdx-diagrams.md +++ b/.claude/rules/mdx-diagrams.md @@ -4,18 +4,20 @@ paths: - "fern/**/*.mdx" --- -# Themed SVG diagrams +# Diagram authoring + +## Themed SVG diagrams Applies to hand-authored SVG diagrams under `fern/assets/images/img/`. Exemplar: `ai-agent-flow-themed.svg`. -## One file, both modes +### One file, both modes Author a single themed SVG and embed it as a plain ``. Do not ship a `.light-only` / `.dark-only` pair — that pattern is for diagrams whose brand colors must not be inverted, not for new work. -## How theming works +### How theming works The site sets `color-scheme` on `html`; it inherits to the `img`, and the browser propagates it into the SVG's own document. So @@ -23,7 +25,7 @@ browser propagates it into the SVG's own document. So toggle. Where a browser hasn't implemented that propagation it falls back to the OS preference, which is what the toggle defaults to anyway. -## Colors +### Colors - Custom properties do not cross document boundaries. Nothing from the page reaches an img-embedded SVG — not Fern's `--accent`, not `--grayscale-*`. @@ -37,18 +39,18 @@ the OS preference, which is what the toggle defaults to anyway. chip `#40E0D0`, on-chip `#0e0e18`. Caller icon matches ink in light mode, matches the chip color in dark mode. -## Filename +### Filename Keep the word `diagram` **out** of the filename. `styles.css` inverts `img.diagram` and `[src*="diagram"]` for dark mode, which wrecks a themed SVG. Name it `-themed.svg`. -## Motion +### Motion Guard every animation with `@media (prefers-reduced-motion: reduce) { … { animation: none; } }`. -## Embedding +### Embedding - Plain `` with meaningful alt text. **No ``** — its border artifact shows in both themes and is worse in dark mode. @@ -57,8 +59,21 @@ Guard every animation with - Wrap the `` in `` and pair it with an `` mermaid block carrying the same information. An SVG reaches agents only as a link. -## When not to use SVG +### When not to use SVG Mermaid is fine for anything whose source is already text and whose labels are short. Reach for a themed SVG when Mermaid truncates long node text or when the diagram carries brand weight. + +## Information diagrams in LLM exports + +Raster diagrams render as image links in the Markdown endpoint. Give human and agent readers equivalent information: + +- Put the complete `` that contains an information-bearing raster diagram inside ``. +- Follow it immediately with `` containing an equivalent in Mermaid or structured Markdown. Preserve the original entities, sequence, branches, labels, and direction; do not substitute a generic summary for relationships visible in the image. +- Choose the format that preserves the information most precisely. Use `sequenceDiagram` for messages between actors and `flowchart` for processes and decisions, but prefer an ordered list or table when it represents exact steps, ordering, or labels more faithfully. +- Do not infer relationships from visual placement alone. A grid or grouped layout may be organizing information rather than defining branches or connections. +- A standalone `` is allowed for a screenshot only when the adjacent prose already states every action or value needed to complete the task. +- Do not pair Mermaid source with these tags. Mermaid already exports as readable source. + +Keep the visibility tags at column 0 with blank lines inside and around each block, as specified in `mdx-mechanics.md`. diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/agent-base.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/agent-base.mdx index 2538f2c1c2..c47a00273c 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/agent-base.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/agent-base.mdx @@ -38,10 +38,30 @@ Before building agents, you should understand: ## Agent Architecture Overview + + Agent components overview. + + + + +```mermaid +flowchart TD + agentClass["Your agent class
extends AgentBase"] --> config["Configuration"] + config --> prompts["Prompts
role, guidelines, rules"] + config --> voice["Voice
language, voice, TTS engine"] + config --> params["AI parameters
timeouts, barge, attention"] + config --> hints["Hints
keywords, names, terms"] + config --> functions["Functions
tools, DataMap, handlers"] + config --> skills["Skills
plugins, add-ons, integrations"] + prompts & voice & params & hints & functions & skills --> swml["Automatically generated SWML output"] +``` + +
+ ## A Complete Agent Example Here's what a production agent looks like across all supported languages: @@ -381,10 +401,31 @@ swaig-test my_agent.py --exec check_order --order_number 12345 ## Class Overview + + AgentBase inheritance diagram. + + + + +```mermaid +classDiagram + AgentBase --|> AuthMixin + AgentBase --|> WebMixin + AgentBase --|> SWMLService + AgentBase --|> PromptMixin + AgentBase --|> ToolMixin + AgentBase --|> SkillMixin + AgentBase --|> AIConfigMixin + AgentBase --|> ServerlessMixin + AgentBase --|> StateMixin +``` + + + ## Constructor Parameters The constructor accepts the agent name plus optional configuration: @@ -588,10 +629,26 @@ agent.data_map # DataMap builder ## Agent Lifecycle + + Agent lifecycle. + + + + +```mermaid +flowchart TD + init["1. Instantiate
initialize mixins, load config, register routes"] --> configure["2. Configure
add languages, prompt sections, tools, and skills"] + configure --> run["3. Start server with run()
create FastAPI app, mount routes, start Uvicorn"] + run --> get["GET / or POST /
return SWML document"] + run --> swaig["POST /swaig
execute SWAIG function"] +``` + +
+ ## Configuration File Load configuration from a YAML/JSON file: diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/architecture.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/architecture.mdx index 2dff289a7f..79ef2a6367 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/architecture.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/architecture.mdx @@ -35,10 +35,30 @@ Before diving into these concepts, you should have: ## The Big Picture + + SignalWire Server SDK Architecture. + + + + +```mermaid +sequenceDiagram + participant Caller + participant Cloud as SignalWire Cloud + participant Agent as Your Agent
AgentBase and SWMLService + Caller->>Cloud: Incoming call + Cloud->>Agent: POST / or POST /swaig + Note over Cloud: Receive call, request SWML,
execute AI, call SWAIG tools + Note over Agent: AuthMixin, WebMixin, PromptMixin,
ToolMixin, SkillMixin, AIConfigMixin,
ServerlessMixin, StateMixin + Agent-->>Cloud: SWML JSON or function result +``` + +
+ ## Key Terminology | Term | Definition | @@ -71,12 +91,34 @@ Understanding these core concepts helps you: ## The Mixin Composition Pattern -AgentBase doesn't inherit from a single monolithic class. Instead, it combines nine specialized mixins plus the SWMLService base class: +AgentBase doesn't inherit from a single monolithic class. Instead, it combines eight specialized mixins plus the SWMLService base class: + + AgentBase mixin composition. + + + + +`AgentBase` inherits from the following classes in method resolution order (MRO): + +| Order | Class | Responsibilities | +|---:|---|---| +| 1 | `AuthMixin` | Basic authentication, credentials, and validation | +| 2 | `WebMixin` | FastAPI, routes, and the server | +| 3 | `SWMLService` | Base class for schema, rendering, and verbs | +| 4 | `PromptMixin` | POM, sections, and templates | +| 5 | `ToolMixin` | SWAIG functions, decorators, and DataMap | +| 6 | `SkillMixin` | Skill management, registry, and loading | +| 7 | `AIConfigMixin` | Languages, hints, and parameters | +| 8 | `ServerlessMixin` | Lambda, CGI, and Azure | +| 9 | `StateMixin` | Session, call state, and persistence | + + + ## Each Mixin's Role ### AuthMixin - Authentication & Security diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/call-flow.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/call-flow.mdx index 00fa681717..008100c34b 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/call-flow.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/call-flow.mdx @@ -17,10 +17,26 @@ answer -> ai The SDK provides three insertion points to customize this flow: + + Call flow insertion points for pre-answer, post-answer, and post-AI verbs. + + + + +```mermaid +flowchart TD + pre["Pre-answer verbs while call rings
ringback, screening, conditional routing"] --> answer["answer verb
automatic when auto_answer=True"] + answer --> postAnswer["Post-answer verbs before AI
welcome messages, disclaimers, hold music"] + postAnswer --> ai["AI verb
conversation"] + ai --> postAI["Post-AI verbs
cleanup, transfers, surveys, logging"] +``` + +
+ ### Verb Insertion Methods | Method | Purpose | Common Uses | diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/call-transfer.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/call-transfer.mdx index d0494c3038..1e705285fd 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/call-transfer.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/call-transfer.mdx @@ -243,10 +243,23 @@ if __name__ == "__main__": ### Transfer Flow + + Diagram showing the flow of permanent and temporary call transfers between agents and destinations. + + + + +| Transfer type | Call flow | Result | +| --- | --- | --- | +| Permanent (`final=True`) | Caller → Agent → “Transferring...” → Destination | The agent exits when it hands the call to the destination. | +| Temporary (`final=False`) | Caller → Agent → “Connecting...” → Destination | When the destination hangs up, the call returns to the agent and the conversation continues. | + + + ### Department Transfer Example diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/concierge.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/concierge.mdx index 67f1b318d0..4be03d6dff 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/concierge.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/concierge.mdx @@ -237,10 +237,27 @@ ConciergeAgent provides these SWAIG functions automatically: ### Concierge Flow + + Diagram showing the concierge flow from greeting through information lookup, service requests, and booking assistance. + + + + +The concierge uses a different tool according to the guest's request: + +```mermaid +flowchart LR + amenity["Amenity question"] --> lookup["Look up the amenity"] --> info["Return hours and location"] + booking["Booking request"] --> availability["Call check_availability()"] --> offer["Report availability and offer to book"] + directions["Directions request"] --> route["Call get_directions()"] --> instructions["Return directions"] +``` + + + ### Complete Example ```python diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/contexts-workflows.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/contexts-workflows.mdx index 2bb269f3d8..82528f58ef 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/contexts-workflows.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/contexts-workflows.mdx @@ -54,10 +54,31 @@ Understanding how contexts, steps, and navigation work together is essential for The AI automatically tracks which context and step the conversation is in. When step criteria are met, it advances to the next allowed step. When context navigation is permitted and appropriate, it switches contexts entirely. + + Diagram showing the hierarchical structure of ContextBuilder, Contexts, and Steps with navigation flow. + + + + +```mermaid +flowchart LR + subgraph builder[ContextBuilder] + subgraph sales["Context: sales"] + info["Step 1: get_info"] --> confirm["Step 2: confirm"] --> process["Step 3: process"] + end + subgraph support["Context: support"] + help["Step 1: help"] + end + sales <--> support + end +``` + + + **How state flows through contexts:** 1. Caller starts in the first step of the default (or specified) context diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/defining-functions.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/defining-functions.mdx index a4ffa519f9..bae6f4a413 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/defining-functions.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/defining-functions.mdx @@ -24,10 +24,30 @@ This chapter covers everything about SWAIG functions: ## How SWAIG Functions Work + + SWAIG function flow diagram. + + + + +```mermaid +sequenceDiagram + participant Caller + participant AI + participant Agent as Your SWAIG endpoint + Caller->>AI: Ask for order 12345 status + Note over AI: Select check_order with
order_number 12345 + AI->>Agent: POST /swaig with function and arguments + Agent-->>AI: SwaigFunctionResult with shipment status + AI-->>Caller: Speak the result +``` + +
+ ## Quick Start Example Here's a complete agent with a SWAIG function: diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/hints.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/hints.mdx index 821466c255..f335d393ee 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/hints.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/hints.mdx @@ -9,10 +9,20 @@ max-toc-depth: 3 ### Why Use Hints? + + Speech hints improving recognition accuracy. + + + + +Without a hint, the STT engine may transcribe “My Acme account” as “My acne account.” Adding “Acme” as a hint tells the engine to listen for that term and preserves the intended transcription. + + + ### Adding Simple Hints The hint methods accept a single string or a list of strings: diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/info-gatherer.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/info-gatherer.mdx index 783988e67f..36c4ac4012 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/info-gatherer.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/info-gatherer.mdx @@ -200,10 +200,30 @@ InfoGathererAgent( ### Flow Diagram + + Diagram showing the InfoGatherer flow from question presentation through answer collection and confirmation. + + + + +```mermaid +flowchart TD + ready["Agent asks whether the user is ready"] --> confirm["User confirms; AI calls start_questions()"] + confirm --> ask["Agent asks the current question"] + ask --> answer["User answers; AI calls submit_answer()"] + answer -->|confirm=true| verify["Verify answer with user"] + answer -->|no confirmation| next{"More questions?"} + verify --> next + next -->|yes| ask + next -->|no| summary["Return summary of all answers"] +``` + + + ### Built-in Functions InfoGatherer provides these SWAIG functions automatically: diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/lifecycle.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/lifecycle.mdx index f1c12beb5d..530059eb02 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/lifecycle.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/lifecycle.mdx @@ -11,18 +11,70 @@ max-toc-depth: 3 Understanding the request lifecycle helps you debug issues and optimize your agents. Here's the complete flow: + + Complete call lifecycle. + + + + +The complete call lifecycle proceeds through these five phases: + +| Step | Phase | Event | +|---:|---|---| +| 1 | Call setup | Caller dials your phone number. | +| 2 | Call setup | SignalWire receives the call. | +| 3 | Call setup | SignalWire checks the number's webhook configuration. | +| 4 | Call setup | SignalWire requests SWML by sending `POST https://your-agent.com/`. | +| 5 | SWML generation | Your agent receives the HTTP request. | +| 6 | SWML generation | The agent builds the SWML document, including prompts, functions, and languages. | +| 7 | SWML generation | The agent generates security tokens for SWAIG functions. | +| 8 | SWML generation | The agent returns a SWML JSON response. | +| 9 | AI conversation | SignalWire executes the SWML, answers the call, and starts the AI. | +| 10 | AI conversation | The AI speaks the greeting from the prompt. | +| 11 | AI conversation | The user speaks; the AI listens and transcribes. | +| 12 | AI conversation | The AI processes the input and responds, continuing the conversation loop. | +| 13 | Function calls, as needed | The AI decides to call a function. | +| 14 | Function calls, as needed | SignalWire sends a `POST` request to `/swaig` with the function name and arguments. | +| 15 | Function calls, as needed | Your agent executes the handler. | +| 16 | Function calls, as needed | The agent returns a `SwaigFunctionResult`. | +| 17 | Function calls, as needed | The AI incorporates the result and continues the conversation. | +| 18 | Call end | The call ends by hangup, transfer, or timeout. | +| 19 | Call end | The AI generates a summary using `post_prompt`. | +| 20 | Call end | SignalWire sends a `POST` request to `/post_prompt` with the summary. | +| 21 | Call end | Your agent receives and processes the summary. | + + + ### Phase 1: Call Setup When a call arrives at SignalWire: + + Call setup phase. + + + + +```mermaid +sequenceDiagram + participant Caller + participant Cloud as SignalWire + participant Agent as Your agent + Caller->>Cloud: Dial SignalWire number + Note over Cloud: Look up webhook configuration
for the called number + Cloud->>Agent: POST / with application/json and Basic Auth +``` + +
+ **Key points:** - SignalWire knows which agent to contact based on phone number configuration @@ -80,10 +132,29 @@ def _render_swml(self, request_body=None): Once SignalWire has the SWML, it executes the instructions: + + AI conversation loop. + + + + +```mermaid +flowchart TD + listen["Listen with STT"] --> transcribe["Transcribe speech"] + transcribe --> intent["Process intent"] + intent --> decision{"Need a function?"} + decision -->|yes| function["Call SWAIG function"] + decision -->|no| response["Generate response"] + function & response --> speak["Speak with TTS"] + speak --> listen +``` + + + **AI Parameters that control this loop:** | Parameter | Default | Purpose | @@ -97,18 +168,51 @@ Once SignalWire has the SWML, it executes the instructions: When the AI needs to call a function: + + SWAIG function call phase. + + + + +```mermaid +sequenceDiagram + participant AI as SignalWire AI + participant Agent as Your agent + AI->>Agent: POST /swaig with Basic Auth,
function name, parsed arguments,
call_id, and global_data + Note over Agent: Validate auth, find handler,
execute function, build response + Agent-->>AI: 200 OK with response and optional actions + Note over AI: Speak response and continue conversation +``` + +
+ ### Phase 5: Call End When the call ends, the post-prompt summary is sent: + + Call ending phase. + + + + +```mermaid +flowchart TD + triggers["Hangup, transfer, stop action,
inactivity timeout, or error"] --> summary["AI generates a summary using post_prompt"] + summary --> webhook["POST /post_prompt with post_prompt_data,
call_id, caller_id_num, and call_duration"] + webhook --> agent["Your agent processes the summary
for logging, CRM updates, or analytics"] +``` + +
+ ### Handling Post-Prompt Configure post-prompt handling in your agent: diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/mcp-gateway.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/mcp-gateway.mdx index 4e076703ad..fd4d4e8233 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/mcp-gateway.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/mcp-gateway.mdx @@ -16,10 +16,36 @@ The MCP Gateway acts as a bridge: it runs MCP servers and exposes their tools as ### Architecture Overview + + Diagram showing the MCP Gateway architecture connecting SignalWire agents to MCP server processes. + + + + +```mermaid +sequenceDiagram + participant Agent as SignalWire Agent + participant Gateway as MCP Gateway + participant Server as MCP Server + Agent->>Gateway: 1. Add skill + Gateway-->>Agent: 2. Query tools + Gateway->>Server: 3. List tools + Server-->>Gateway: 4. Tool list + Agent->>Gateway: 5. SWAIG call + Gateway->>Server: 6. Spawn session + Gateway->>Server: 7. Call MCP tool + Server-->>Gateway: 8. MCP response + Gateway-->>Agent: 9. SWAIG response + Agent->>Gateway: 10. Call hangup + Gateway->>Server: 11. Close session +``` + + + ### When to Use MCP Gateway **Good use cases:** diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/multi-agent.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/multi-agent.mdx index 41c18c206e..36cc889fbd 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/multi-agent.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/multi-agent.mdx @@ -277,10 +277,26 @@ server.register(BillingAgent()) # Uses "/billing" ### Server Architecture + + Diagram showing AgentServer routing requests to different agents based on URL path. + + + + +```mermaid +flowchart TD + server["AgentServer
FastAPI application"] --> sales["/sales
Sales Agent"] + server --> support["/support
Support Agent"] + server --> billing["/billing
Billing Agent"] + sales & support & billing --> routes["Each agent exposes:
GET or POST /route for SWML
POST /route/swaig for functions
POST /route/post_prompt for post-prompt handling"] +``` + +
+ ### Managing Agents #### Get All Agents @@ -345,10 +361,26 @@ When `auto_map=True`, the server automatically creates mappings: ### SIP Routing Flow + + Diagram showing how SIP usernames are mapped to agent routes through the AgentServer. + + + + +```mermaid +flowchart TD + call["SIP call to sip:sales-team@example.com"] --> endpoint["POST /sip routing endpoint"] + endpoint --> username["Extract username: sales-team"] + username --> route["Look up route: /sales"] + route --> swml["Return SWML from Sales Agent"] +``` + + + ### Health Check Endpoint AgentServer provides a built-in health check: diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/prompts-pom.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/prompts-pom.mdx index c461114fcb..acc8b01e8d 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/prompts-pom.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/prompts-pom.mdx @@ -29,10 +29,27 @@ max-toc-depth: 3 ### POM Structure + + POM hierarchy structure. + + + + +```mermaid +flowchart TD + prompt["Prompt"] --> role["Section: Role
body"] + prompt --> guidelines["Section: Guidelines
body and bullets"] + prompt --> rules["Section: Rules
body and subsections"] + rules --> security["Subsection: Security
bullets"] + rules --> privacy["Subsection: Privacy
bullets"] +``` + +
+ ### Adding Sections #### Basic Section with Body diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/receptionist.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/receptionist.mdx index 98ab68a433..f4750bcc41 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/receptionist.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/receptionist.mdx @@ -223,10 +223,28 @@ ReceptionistAgent provides these SWAIG functions automatically: ### Call Flow + + Diagram showing the receptionist flow from greeting through caller info collection to department transfer. + + + + +```mermaid +flowchart TD + greet["Greet caller"] --> collect["Collect caller name and reason for calling"] + collect --> store["AI calls collect_caller_info()
and stores it in global_data"] + store --> department["Match the reason to a department"] + department --> confirm["Confirm the proposed transfer"] + confirm --> transfer["AI calls transfer_call()
with the department number"] + transfer --> complete["Call transfers"] +``` + +
+ ### Complete Example ```python diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/search-knowledge.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/search-knowledge.mdx index c69d525255..0081ce8207 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/search-knowledge.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/search-knowledge.mdx @@ -49,10 +49,26 @@ Agent -> native_vector_search skill -> SearchEngine -> Results | pgvector | PostgreSQL extension for production deployments | | Remote | Network mode for centralized search servers | + + Diagram showing the search flow from agent query through vector search to document results. + + + + +```mermaid +flowchart TD + question["User asks: What is the return policy?"] --> tool["AI calls search_documents()
with query: return policy"] + tool --> engine["SearchEngine performs vector similarity,
keyword matching, metadata filtering,
and result ranking"] + engine --> results["Return top matching document excerpts"] + results --> answer["AI synthesizes an answer from the results"] +``` + +
+ ### Building Search Indexes Use the `sw-search` CLI to create search indexes: diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/skill-config.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/skill-config.mdx index d1d6260de3..ea3bd8dd83 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/skill-config.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/skill-config.mdx @@ -227,10 +227,26 @@ self.add_skill("web_search", { ### Configuration Validation + + Skill configuration validation flow diagram. + + + + +```mermaid +flowchart TD + add["add_skill() called with parameters"] --> instantiate["Instantiate skill
store self.params and extract swaig_fields"] + instantiate --> setup["Run setup()
validate packages, environment, and custom rules"] + setup -->|success| register["Call register_tools()"] + setup -->|failure| error["Raise ValueError"] +``` + +
+ ### Complete Configuration Example ```python diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/state-management.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/state-management.mdx index a0b4c52a5a..0eac9d0415 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/state-management.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/state-management.mdx @@ -26,10 +26,28 @@ If you need data to persist across calls (like customer profiles or order histor 5. When the call ends, `post_prompt` runs to extract structured data 6. All in-memory state is cleared + + Diagram showing how state flows through agent initialization, prompt substitution, SWAIG functions, and post-prompt processing. + + + + +```mermaid +flowchart TD + start["Call starts"] --> initial["set_global_data()
initialize state from agent configuration"] + initial --> conversation["Conversation
prompts substitute global_data keys"] + conversation --> function["Function call
handler receives raw_data and call information"] + function --> result["SwaigFunctionResult
update_global_data() updates session state;
set_metadata() updates function-scoped data"] + result --> ending["Call ends"] + ending --> post["Post-prompt extracts structured conversation data"] +``` + +
+ ### State Types Overview | State Type | Scope | Key Features | diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/survey.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/survey.mdx index edaa3cd6c8..73ed52f9f6 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/survey.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/survey.mdx @@ -249,10 +249,33 @@ Survey handlers return `FunctionResult(string)` objects (not plain dicts). If ex ### Survey Flow + + Diagram showing the survey flow from introduction through question presentation, validation, and conclusion. + + + + +```mermaid +flowchart TD + intro["Introduction"] --> ask["Ask question"] + ask --> response["Get response"] + response --> valid{"Valid?"} + valid -->|yes| log["Log response"] + valid -->|no| retry["Retry up to max_retries"] + retry -->|valid| log + retry -->|still invalid| fallback["Skip or ask again"] + log & fallback --> more{"More questions?"} + more -->|yes| ask + more -->|no| conclusion["Conclusion"] + conclusion --> summary["Generate summary"] +``` + + + ### Complete Example ```python diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/swaig.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/swaig.mdx index a55e02c970..33b743b1fd 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/swaig.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/swaig.mdx @@ -14,10 +14,31 @@ max-toc-depth: 3 SWAIG (SignalWire AI Gateway) connects the AI conversation to your backend logic. When the AI decides it needs to perform an action (like looking up an order or checking a balance), it calls a SWAIG function that you've defined. + + SWAIG function call flow. + + + + +```mermaid +sequenceDiagram + participant User + participant AI as SignalWire AI Engine + participant Agent as Your agent + User->>AI: What is my account balance? + Note over AI: Transcribe speech, understand intent,
select get_balance(account_id) + AI->>Agent: POST /swaig with function and arguments + Note over Agent: Look up balance and return
SwaigFunctionResult + Agent-->>AI: Balance is $150.00 + AI-->>User: Speak the result +``` + +
+ ### SWAIG in SWML When your agent generates SWML, it includes SWAIG function definitions in the `ai` verb: @@ -540,10 +561,31 @@ return result; ### SWAIG Request Flow + + SWAIG request processing flow. + + + + +```mermaid +flowchart TD + request["SignalWire sends POST /swaig"] --> basic["Validate Basic Auth"] + basic --> token["Validate function-specific token, if configured"] + token --> lookup["Look up function in ToolRegistry"] + lookup -->|found| handler["Execute handler"] + handler --> result["Return SwaigFunctionResult"] + result --> json["Format JSON response"] + lookup -->|not found| error["Return error response"] + json & error --> response["Send response to SignalWire"] + response --> continue["AI incorporates response into conversation"] +``` + + + ### SWAIG Request Format SignalWire sends a POST request with this structure: diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/swml.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/swml.mdx index a1d9ab5689..5326cc5e69 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/swml.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/swml.mdx @@ -12,10 +12,26 @@ max-toc-depth: 3 SWML (SignalWire Markup Language) is a document that instructs SignalWire how to handle a phone call. SWML can be written in JSON or YAML format -- **this guide uses JSON throughout**. When a call comes in, SignalWire requests SWML from your agent, then executes the instructions. + + SWML request and response flow. + + + + +```mermaid +flowchart TD + call["Call arrives"] --> request["SignalWire sends POST https://your-agent.com/"] + request --> response["Your agent returns SWML JSON"] + response --> execute["SignalWire executes the SWML instructions"] + execute --> conversation["AI conversation begins from the SWML configuration"] +``` + + + ### SWML Document Structure Every SWML document has this structure: @@ -364,10 +380,32 @@ When SignalWire requests SWML, the agent's render method (`_render_swml()` in Py ### SWML Rendering Pipeline + + SWML rendering pipeline. + + + + +```mermaid +flowchart TD + request["POST / arrives"] --> render["_render_swml()"] + render --> prompt["Get prompt: text or POM"] + render --> postPrompt["Get post-prompt"] + render --> functions["Collect SWAIG functions"] + render --> tokens["Generate security tokens"] + render --> urls["Build webhook URLs"] + render --> params["Collect hints, languages, and parameters"] + prompt & postPrompt & functions & tokens & urls & params --> ai["Assemble AI verb"] + ai --> document["Build document: answer and AI verbs"] + document --> response["Return SWML JSON"] +``` + + + ### Viewing Your SWML You can see the SWML your agent generates: diff --git a/fern/products/server-sdks/pages/guides/build-ai-agents/understanding-skills.mdx b/fern/products/server-sdks/pages/guides/build-ai-agents/understanding-skills.mdx index ea30c7900a..1d1568cce6 100644 --- a/fern/products/server-sdks/pages/guides/build-ai-agents/understanding-skills.mdx +++ b/fern/products/server-sdks/pages/guides/build-ai-agents/understanding-skills.mdx @@ -582,10 +582,27 @@ Let's start by understanding how skills work internally. ## Skill Architecture + + Skill loading process diagram. + + + + +```mermaid +flowchart TD + add["Agent calls add_skill()"] --> lookup["SkillRegistry looks up the class
in loaded skills, built-ins, then external paths"] + lookup --> instantiate["SkillManager creates the skill
with agent reference and configuration"] + instantiate --> setup["setup() validates packages and environment,
then initializes APIs or connections"] + setup --> register["register_tools() adds SWAIG functions"] + register --> apply["Apply prompts, speech hints, and global data"] +``` + +
+ ### SkillBase (Abstract Base Class) **Required Methods:** diff --git a/fern/products/server-sdks/pages/guides/deploy/cgi-mode.mdx b/fern/products/server-sdks/pages/guides/deploy/cgi-mode.mdx index e951123bf3..b7f6754f23 100644 --- a/fern/products/server-sdks/pages/guides/deploy/cgi-mode.mdx +++ b/fern/products/server-sdks/pages/guides/deploy/cgi-mode.mdx @@ -126,10 +126,27 @@ chmod +x agent.py agent.pl ## CGI request flow + + CGI request flow diagram showing web server, CGI script execution, and SignalWire Cloud. + + + + +```mermaid +flowchart TD + cloud["SignalWire"] --> server["Apache or nginx web server"] + server -->|"Set CGI environment: GATEWAY_INTERFACE, PATH_INFO, CONTENT_LENGTH"| script["Python CGI script: agent.py"] + script -->|PATH_INFO empty| swml["Return SWML document"] + script -->|PATH_INFO=/swaig| function["Execute SWAIG function"] + swml & function --> stdout["Write JSON response to stdout
for the web server"] +``` + +
+ ## Apache configuration ### Enable CGI diff --git a/fern/products/server-sdks/pages/guides/deploy/docker-kubernetes.mdx b/fern/products/server-sdks/pages/guides/deploy/docker-kubernetes.mdx index aef1d88a56..936a7d02fa 100644 --- a/fern/products/server-sdks/pages/guides/deploy/docker-kubernetes.mdx +++ b/fern/products/server-sdks/pages/guides/deploy/docker-kubernetes.mdx @@ -438,10 +438,27 @@ stringData: ## Kubernetes architecture + + Kubernetes architecture diagram showing pods, services, ingress, and SignalWire Cloud. + + + + +```mermaid +flowchart TD + internet["Internet"] --> ingress["Ingress: nginx or Traefik
SSL termination and routing"] + ingress --> service["ClusterIP Service
load balancing across pods"] + service --> pod1["Agent pod 1"] + service --> pod2["Agent pod 2"] + service --> pod3["Agent pod 3"] +``` + +
+ ## Deploying to Kubernetes ```bash diff --git a/fern/products/server-sdks/pages/guides/deploy/production.mdx b/fern/products/server-sdks/pages/guides/deploy/production.mdx index ee763c9927..1525684cd0 100644 --- a/fern/products/server-sdks/pages/guides/deploy/production.mdx +++ b/fern/products/server-sdks/pages/guides/deploy/production.mdx @@ -360,10 +360,26 @@ sudo systemctl reload nginx ## Production architecture + + Production architecture diagram showing nginx, uvicorn workers, and SignalWire Cloud. + + + + +```mermaid +flowchart TD + internet["Internet"] --> loadBalancer["Optional load balancer
for high availability"] + loadBalancer --> nginx["nginx reverse proxy
SSL termination and rate limiting"] + nginx --> workers["Uvicorn and agent
multiple workers"] + workers --> apis["External APIs, databases, and services"] +``` + +
+ ## SSL configuration ### Using environment variables diff --git a/fern/products/server-sdks/pages/guides/deploy/serverless.mdx b/fern/products/server-sdks/pages/guides/deploy/serverless.mdx index 64236fa065..baddcb842e 100644 --- a/fern/products/server-sdks/pages/guides/deploy/serverless.mdx +++ b/fern/products/server-sdks/pages/guides/deploy/serverless.mdx @@ -251,10 +251,27 @@ functions: ### Lambda request flow + + Lambda request flow diagram showing API Gateway, Lambda function, and SignalWire Cloud. + + + + +```mermaid +flowchart TD + cloud["SignalWire"] --> gateway["API Gateway
HTTPS endpoint"] + gateway --> lambda["Lambda function
agent.run(event, context)"] + lambda -->|path /| swml["Return SWML document"] + lambda -->|path /swaig| function["Execute SWAIG function"] + swml & function --> response["Return JSON response to SignalWire"] +``` + +
+ ## Google Cloud Functions ### Cloud Functions handler diff --git a/fern/products/server-sdks/pages/guides/getting-started/exposing-agents.mdx b/fern/products/server-sdks/pages/guides/getting-started/exposing-agents.mdx index 05f1d1349e..c2f0daf359 100644 --- a/fern/products/server-sdks/pages/guides/getting-started/exposing-agents.mdx +++ b/fern/products/server-sdks/pages/guides/getting-started/exposing-agents.mdx @@ -13,14 +13,46 @@ max-toc-depth: 3 SignalWire's cloud needs to reach your agent via HTTP: + + Diagram showing that SignalWire's cloud cannot reach your agent running on localhost. + + + + +```mermaid +flowchart LR + cloud["SignalWire Cloud"] -. "cannot reach a private address" .-> local["Your agent
localhost:3000"] +``` + +
+ + + Diagram showing ngrok creating a public tunnel from SignalWire's cloud to your local agent. + + + + +```mermaid +sequenceDiagram + participant Cloud as SignalWire Cloud + participant Ngrok as ngrok cloud tunnel
https://abc123.ngrok.io + participant Agent as Your agent
http://localhost:3000 + Cloud->>Ngrok: HTTP request to public URL + Ngrok->>Agent: Forward request through tunnel + Agent-->>Ngrok: HTTP response + Ngrok-->>Cloud: Forward response +``` + +
+ ### Installing ngrok #### macOS (Homebrew) diff --git a/fern/products/server-sdks/pages/guides/getting-started/overview.mdx b/fern/products/server-sdks/pages/guides/getting-started/overview.mdx index e3a7bbaee2..aec6621076 100644 --- a/fern/products/server-sdks/pages/guides/getting-started/overview.mdx +++ b/fern/products/server-sdks/pages/guides/getting-started/overview.mdx @@ -122,10 +122,24 @@ You will have: - Accessible via public URL - Ready to connect to SignalWire phone numbers + + Getting Started Overview. + + + + +```mermaid +flowchart LR + cloud["SignalWire Cloud"] <--> tunnel["ngrok public tunnel"] + tunnel <--> agent["Your agent
localhost:3000"] +``` + +
+ ## What is the SignalWire SDK? The SignalWire SDK lets you create **voice AI agents** - intelligent phone-based assistants that can: @@ -138,10 +152,32 @@ The SignalWire SDK lets you create **voice AI agents** - intelligent phone-based ## How It Works + + High-Level Architecture. + + + + +```mermaid +sequenceDiagram + participant Caller + participant Cloud as SignalWire Cloud + participant Agent as Your Python agent + Caller->>Cloud: Phone call + Cloud->>Agent: SWML request + Agent-->>Cloud: SWML response + Note over Cloud: Route call, run AI,
handle TTS and STT + Cloud->>Agent: Function calls + Note over Agent: Define AI behavior,
provide functions, handle webhooks + Agent-->>Cloud: Function results +``` + +
+ **The flow:** 1. A caller dials your SignalWire phone number diff --git a/fern/products/server-sdks/pages/guides/getting-started/quickstart.mdx b/fern/products/server-sdks/pages/guides/getting-started/quickstart.mdx index f906008d5c..f977bba828 100644 --- a/fern/products/server-sdks/pages/guides/getting-started/quickstart.mdx +++ b/fern/products/server-sdks/pages/guides/getting-started/quickstart.mdx @@ -363,10 +363,30 @@ agent.Run(); You'll see output like: + + Agent startup output showing security configuration, service initialization, basic auth credentials, and server startup information. + + + + +Representative startup output (the Basic Auth password is generated for each run): + +```text +Starting My First Agent... +Server running at: http://localhost:3000 +Press Ctrl+C to stop +Agent available at: http://localhost:3000 +Basic Auth: signalwire: +Uvicorn running on http://0.0.0.0:3000 +Application startup complete. +``` + + + The SDK shows: diff --git a/fern/products/server-sdks/pages/guides/manage-resources/account-setup.mdx b/fern/products/server-sdks/pages/guides/manage-resources/account-setup.mdx index 52aa59e60b..2ac18842b0 100644 --- a/fern/products/server-sdks/pages/guides/manage-resources/account-setup.mdx +++ b/fern/products/server-sdks/pages/guides/manage-resources/account-setup.mdx @@ -23,10 +23,27 @@ This chapter covers SignalWire integration: ## Integration Overview + + SignalWire integration overview. + + + + +```mermaid +flowchart LR + caller["Caller phone"] --> network["SignalWire network"] + network --> server["Your server
returns SWML"] + server --> agent["Agent logic"] +``` + +When the caller dials your number, SignalWire receives the call, requests SWML from your server, and uses your agent logic to handle the conversation. + +
+ ## Prerequisites Before connecting to SignalWire: @@ -72,10 +89,28 @@ Before connecting to SignalWire: ## Architecture + + Call flow architecture between SignalWire and your agent. + + + + +```mermaid +sequenceDiagram + participant Cloud as SignalWire Cloud
SWML processor + participant Agent as Your server
agent + Note over Cloud: Receive inbound call, fetch SWML,
execute AI verbs, handle speech + Cloud->>Agent: HTTPS request for SWML or SWAIG function + Note over Agent: Return SWML, handle functions,
run business logic + Agent-->>Cloud: SWML document or function result +``` + +
+ ## Required URLs Your agent needs to be accessible at these endpoints: diff --git a/fern/products/server-sdks/pages/guides/manage-resources/mapping-numbers.mdx b/fern/products/server-sdks/pages/guides/manage-resources/mapping-numbers.mdx index 152a35247f..39881f3f13 100644 --- a/fern/products/server-sdks/pages/guides/manage-resources/mapping-numbers.mdx +++ b/fern/products/server-sdks/pages/guides/manage-resources/mapping-numbers.mdx @@ -9,10 +9,26 @@ max-toc-depth: 3 SignalWire uses **SWML Script** resources to connect phone numbers to your agent. When a call comes in, SignalWire fetches SWML from your agent's URL and executes it. + + Caller dials a SignalWire number and the call is routed to your agent. + + + + +```mermaid +flowchart LR + number["SignalWire phone number"] --> url["Configured Voice URL"] + url --> agent["Agent route"] +``` + +For each incoming call, SignalWire sends a POST request to the number's Voice URL, your server returns SWML, and SignalWire executes that SWML to run the selected agent. + + + ### Step 1: Create a SWML Script Resource 1. Log in to SignalWire dashboard @@ -26,18 +42,26 @@ SignalWire uses **SWML Script** resources to connect phone numbers to your agent - Format: `https://user:pass@your-domain.com/agent` 6. Click **Create** + + Creating a new SWML Script resource in the SignalWire dashboard. + + ### Step 2: Add a Phone Number or Address -After creating the script, you'll see the resource configuration page: +After creating the script, you'll see the resource configuration page. + + Resource configuration page in the SignalWire dashboard. + + 1. Click the **Addresses & Phone Numbers** tab 2. Click **+ Add** 3. Choose your address type: @@ -47,10 +71,14 @@ After creating the script, you'll see the resource configuration page: 4. Follow the prompts to select or purchase a phone number 5. Your number is now connected to your agent! + + Adding a phone number or address to a SWML Script resource. + + ### Step 3: Test Your Setup 1. Ensure your agent is running locally diff --git a/scripts/llm-export-cases.json b/scripts/llm-export-cases.json index ee1a9613ff..3c305dde98 100644 --- a/scripts/llm-export-cases.json +++ b/scripts/llm-export-cases.json @@ -176,5 +176,76 @@ "contains": [ "#### Not legal advice" ] + }, + { + "name": "Server SDK information diagrams", + "paths": [ + "/server-sdks.md", + "/server-sdks/guides/account-setup.md", + "/server-sdks/guides/agent-base.md", + "/server-sdks/guides/architecture.md", + "/server-sdks/guides/call-flow.md", + "/server-sdks/guides/cgi-mode.md", + "/server-sdks/guides/concierge.md", + "/server-sdks/guides/contexts-workflows.md", + "/server-sdks/guides/defining-functions.md", + "/server-sdks/guides/docker-kubernetes.md", + "/server-sdks/guides/exposing-agents.md", + "/server-sdks/guides/info-gatherer.md", + "/server-sdks/guides/lifecycle.md", + "/server-sdks/guides/mapping-numbers.md", + "/server-sdks/guides/mcp-gateway.md", + "/server-sdks/guides/multi-agent.md", + "/server-sdks/guides/production.md", + "/server-sdks/guides/prompts-pom.md", + "/server-sdks/guides/receptionist.md", + "/server-sdks/guides/search-knowledge.md", + "/server-sdks/guides/serverless.md", + "/server-sdks/guides/skill-config.md", + "/server-sdks/guides/state-management.md", + "/server-sdks/guides/survey.md", + "/server-sdks/guides/swaig.md", + "/server-sdks/guides/swml.md", + "/server-sdks/guides/understanding-skills.md" + ], + "contains": [ + "```mermaid" + ], + "notContains": [ + "/assets/images/sdks/diagrams/" + ] + }, + { + "name": "Server SDK call-transfer diagram", + "path": "/server-sdks/guides/call-transfer.md", + "contains": [ + "| Permanent (`final=True`)", + "The agent exits when it hands the call to the destination.", + "When the destination hangs up, the call returns to the agent" + ], + "notContains": [ + "/assets/images/sdks/diagrams/" + ] + }, + { + "name": "Server SDK speech-hints diagram", + "path": "/server-sdks/guides/hints.md", + "contains": [ + "Without a hint, the STT engine may transcribe" + ], + "notContains": [ + "/assets/images/sdks/diagrams/" + ] + }, + { + "name": "Server SDK quickstart output", + "path": "/server-sdks/guides/quickstart.md", + "contains": [ + "Server running at: http://localhost:3000", + "Basic Auth: signalwire:" + ], + "notContains": [ + "/assets/images/sdks/diagrams/" + ] } ]