# Introduction to SWML SignalWire Markup Language (SWML) lets you write Relay applications using simple statements in a YAML or a JSON document. [Relay applications](/sdks/overview/what-is-relay) are programs connected to the SignalWire network through a real-time WebSocket connection. They can dynamically and interactively use the services offered by SignalWire, including [**voice calls**](/guides/first-steps-with-voice), [**video conferences**](/guides/video-first-steps), [**messaging**](/guides/first-steps-with-messaging) and [**chat**](/guides/chat-first-steps). SWML also allows you to instantiate [**AI agents**](/swml/guides/ai/getting-started). AI Agents hold natural conversations with the caller, and perform actions intuitively based on the resources you have specified (like REST API endpoints or SWAIG functions). On your SignalWire Dashboard, you can configure SMWL scripts to be executed in response to a phone call, through a Relay script, or when a subscriber calls a SWML resource. You can write and store SWML on the SignalWire Dashboard, but you can also serve SWML scripts directly from a web server. You can even respond with dynamically generated SWML scripts. ## **SWML and Call Fabric Resource Addresses** SWML is the best-supported way to use the new Call Fabric paradigm. To access a Resource, simply reference its Address using this syntax: text space_name.signalwire.com/context/address Each **Resource Address** has two components: - **Context**: A identifier that indicates in which [context](/guides/administration/guides/signalwire-space/what-is-call-fabric/index.mdx#contexts) the resource is located. - **Name**: The name is the unique identifier for the resource. For example, the address for a Subscribers resource named Alice in the public context would be /public/Alice. Learn more by reading our [Introduction to Call Fabric](/guides/administration/guides/signalwire-space/what-is-call-fabric/index.mdx) or the guide to [Managing Resources](/guides/administration/guides/signalwire-space/managing-your-signalwire-resources/index.mdx). ## **Writing SWML** SWML documents are written in YAML or its equivalent JSON. The following SWML script will answer a call, play some music, then hang up: yaml andJson version: 1.0.0 sections: main: - answer: {} - execute: dest: play_music params: to_play: https://cdn.signalwire.com/swml/April_Kisses.mp3 play_music: - play: url: %{params.to_play} Let us walk through the components of this script. ### version Every SWML script starts with a version string. Version 1.0.0 is the latest, and the only supported version. ### sections Each SWML script is divided into sections, which are arrays of statements and methods to execute. Methods that dont expect parameters are be mentioned as strings (like [answer](./methods/answer.mdx)). Methods with parameters are invoked as objects (like [execute](./methods/execute.mdx) and [play](./methods/play.mdx)). Every SWML script must have the main section, which is where execution starts. You can switch to other sections by using either the [execute](./methods/execute.mdx) method or the [transfer](./methods/transfer.mdx) method. Sections behave like functions when you invoke them with the [execute](./methods/execute.mdx) method, but when you invoke a section using [transfer](./methods/transfer.mdx), control is transferred to the new section and doesnt return. In the example above, we have two sections: main and play_music. The main section first answers the call. Then it executes the play_music section which calls the [play](./methods/play.mdx) method. ### Variable substitution and expression evaluation Anything inside a %{ } bracket is considered a JavaScript expression. This can be used to insert variables in SWML. In the example, params passed through the [execute](./methods/execute.mdx) method are accessed by%{params.to_play}. If we wanted to lowercase the URL, we could have written %{params.to_play.toLowerCase()}. ### AI in SWML You can use the [AI methods](./methods/ai/index.mdx) to very quickly create flexible AI agents. yaml andJson version: 1.0.0 sections: main: - ai: post_prompt_url: https://example.com/my-api prompt: text: | You are Franklins assistant, and your job is to collect messages for him over the phone. You can reassure that Franklin will get in touch as soon as possible. Collect the users name and number if you do not already know it from the caller id. Start by presenting yourself, then let the contact know that Franklin is not available, then offer to collect a message. After collecting the message, do not wait for the user to end the conversation: say good bye and hang up the call. post_prompt: text: | Summarize the message as a valid anonymous json object by filling the upper case placeholders in this template: { contact_info: { name: CONTACT_NAME, number: CONTACT_PHONE }, message: MESSAGE } In this example, we instantiate an AI agent with instructions to get messages from the caller. Once the call ends, the post_prompt text will summarize the conversation and HTTP POST it to the post_prompt_url. Check out our [AI Santa](./guides/AI/holiday-special-santa-ai/index.mdx) guide for a complete example. ## **Serving SWML** ### From the Dashboard :::tip This use case is described in detail in the [Making and Receiving Phone Calls](/guides/voice/making-and-receiving-phone-calls) guide. ::: You can write and save new SWML scripts from the Relay/SWML section of your Dashboard. In that section, switch to the tab named [SWML Scripts](https://my.signalwire.com/relay-bins). Once there, you can create a new SWML script: After you save the SWML, navigate to the [Phone Numbers](https://my.signalwire.com/phone_numbers) page. Open the settings for a phone number you own (you may have to buy a new one), and configure it to handle incoming calls using the SWML script you just saved. ### From a web server :::tip This use case is described in detail in the [Handling Incoming Calls from Code](/swml/guides/remote_server) guide. ::: In the phone number settings, when you check the Use External URL for SWML Script handler? option, you can set a Web URL that will serve the SWML script. Every time a call comes in (or some other designated event occurs), youll get a HTTP POST request to the URL with the following JSON parameters: | Parameter | Type | Description | | --: | | - | | call | [Call](#the-call-object) object | Contains properties describing the call. | | vars | any object | Contains the list of variables set in the calling SWML. Empty when invoked as a direct response to a call. | | params | any object | Contains the list of params set by the calling SWML. Empty when invoked as a direct response to a call. | The following is an example JSON that you might receive as a POST request on your server when a SWML is requested. json { call: { call_state: created, direction: inbound, type: phone, from:
Possible values: inbound, outbound | | type | string | The type of call.
Possible values: sip, phone | | from | string | The number/URI that initiated this call. | | to | string | The number/URI of the destination of this call. | | headers | object[] | The headers associated with this call. | | headers.name | string | The name of the header. | | headers.value | string | The value of the header. | | project_id | string | The Project ID this call belongs to. | | space_id | string | The Space ID this call belongs to. | The vars object and the params object will be empty for a new call. If youre executing a remote SWML script using the [execute](./methods/execute.mdx) or [transfer](./methods/execute.mdx) methods, the vars parameter has a list of the variables declared in the script so far. And the params object has the list of parameters explicitly set by the [execute](./methods/execute.mdx) or [transfer](./methods/execute.mdx) methods. You can also reference the properties of call and params objects during the script execution using the variable subtitution bracket like so: yaml andJson version: 1.0.0 sections: main: - play: url: say:%{call.from} Further, consider the following SWML script: yaml andJson # hosted on https://example.com/swml.yaml version: 1.0.0 sections: main: - play: url: %{params.file} - return: 1 It references params.file in its [play](./methods/play.mdx) method. If this SWML was invoked as a response to a phone call, it would cause an error as the params object is empty. But if it was hosted on a server and called with the [execute](./methods/execute.mdx) or the [transfer](./methods/transfer.mdx) method, the params object is passed into the SWML. The SWML above can be invoked as follows: yaml andJson version: 1.0.0 sections: main: execute: dest: https://example.com/swml.yaml params: file: https://cdn.signalwire.com/swml/audio.mp3 ### From a Relay application You can also execute SWML from a Relay application. The following is an snippet using the [RealTime API](/sdks/reference/realtime-sdk). javascript const { Voice } = require(@signalwire/realtime-api); const script = version: 1.0.0 sections: main: - answer: {} - execute: dest: play_music params: to_play: https://cdn.signalwire.com/swml/April_Kisses.mp3 play_music: - play: url: %{params.to_play} ; const client = new Voice.Client({ project: