The SDK provides three layers of security for protecting agent endpoints:
- Basic Authentication -- username/password for all SWML and SWAIG endpoints
- HMAC Token Signing -- per-function tokens that prevent unauthorized tool invocations
- SSL/TLS -- encrypted transport with certificate configuration
By default, the SDK auto-generates a random username and password at startup. Every request to the agent's SWML and SWAIG endpoints must include valid basic auth credentials.
use signalwire::agent::{AgentBase, AgentOptions};
use signalwire::swaig::FunctionResult;
use signalwire::security::SessionManager;
use serde_json::json;
let mut agent = AgentBase::new(AgentOptions::new("security-guide"));let agent = AgentBase::new(AgentOptions::new("my-agent"));
let (user, pass) = agent.get_basic_auth_credentials();
println!("Auth: {user}:{pass}");let mut opts = AgentOptions::new("my-agent");
opts.basic_auth_user = Some("myuser".to_string());
opts.basic_auth_password = Some("mypassword".to_string());
let agent = AgentBase::new(opts);export SWML_BASIC_AUTH_USER=myuser
export SWML_BASIC_AUTH_PASSWORD=mypasswordEnvironment variables override programmatic values.
When a tool is defined with secure: true, the SDK generates an HMAC-SHA256 token for that function's URL. The token is included in the SWML document. When the platform calls the function, it sends the token in the request. The SDK verifies the token before dispatching to the handler.
agent.define_tool(
"transfer_funds",
"Transfer money",
json!({"amount": {"type": "number"}}),
Box::new(|args, _raw| FunctionResult::with_response("Done.")),
true, // <-- secure: generates HMAC token
);- At SWML render time, the SDK mints
token = HMAC-SHA256(secret, "call_id:function_name:expiry:nonce")for each secure tool and appends it to that tool'sweb_hook_urlas a__token=<token>query parameter. An insecure tool gets no__token. - When the platform POSTs to the function, it passes the
__tokenback - The SDK re-derives the HMAC and compares it in constant time, also checking the token's function name, call id, and expiry
- If verification fails on a secure function, the SDK refuses to execute it and
returns a spoken refusal rather than dispatching to the handler. An insecure
function is dispatched regardless —
secure: falseopts out of the check.
export SWML_SSL_ENABLED=true
export SWML_SSL_CERT_PATH=/path/to/cert.pem
export SWML_SSL_KEY_PATH=/path/to/key.pemSSL is configured via the underlying service options. The agent reads the environment variables automatically.
When running behind a reverse proxy (e.g. nginx, AWS ALB), the SDK needs to know the public URL to generate correct webhook URLs in SWML:
export SWML_PROXY_URL_BASE=https://agents.example.comagent.manual_set_proxy_url("https://agents.example.com");The SessionManager handles:
- Session ID tracking across requests
- Credential rotation support
- Token validation for secure functions
let session_manager = SessionManager::with_defaults();- Always use basic auth in production -- even if your agent is behind a firewall
- Use secure functions for sensitive tools -- transfers, payments, data access
- Enable SSL -- especially when the agent is publicly accessible
- Set SWML_PROXY_URL_BASE -- when behind a reverse proxy, to prevent URL mismatches
- Rotate credentials -- change auth credentials periodically
- Limit tool access -- use
set_functions()on steps to restrict which tools are available at each stage