I want to send custom header when Customer tell to...
# ask-ai
p
I want to send custom header when Customer tell to transfer the call to human agent like then ai agent should update the participants and add the custom headers and send BYE to a carrieer the as per the header they handle the routing to a queue or transfer like that then the call or customer is conected to a agent or something like a login on carrier side so they can now talk for this i want to pass the custom headers when send a BYE so how we can setup this what kind of setups we need to do and all this things are possble on self hosting or not
✅ 1
t
Thanks for reaching out, Vasoya. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — that makes sense and I can help. You want the AI agent to update participants, add custom headers, and send a SIP BYE to a carrier so the carrier can route the call (queue/transfer) — and you want to know what setup is required and whether this can be done on self-hosted LiveKit. Before I give concrete steps, I need a few details so I point you to the correct approach: 1. Are you using SIP for the carrier connection (SIP INVITE/BYE) or some other protocol/webhook to the carrier? 2. Are you using LiveKit’s built-in SIP gateway (or a third‑party SBC/VoIP gateway) to connect to the carrier, or do you plan to send SIP messages directly from your application server? 3. Do you control the carrier side (can they accept arbitrary custom headers on BYE) and/or have a spec for which header names and values they expect? 4. Are you self-hosting LiveKit or using a managed LiveKit instance? 5. Which component is sending the BYE: the AI agent logic (your application) or LiveKit server/plugin? Who currently owns SIP signaling in your architecture? Why I ask: the recommended implementation depends on where SIP signaling lives. If your application sends the BYE (and LiveKit only handles media), you can add any SIP headers your carrier accepts. If LiveKit or a gateway handles signaling, the gateway needs to support adding custom SIP headers on BYE. What you can do (high level options based on how signaling is handled): • If your application handles SIP signaling (app-controlled BYE) ◦ Have the AI agent update participant metadata in LiveKit as needed. ◦ When deciding to transfer, construct and send a SIP BYE from your SIP stack including the custom headers the carrier requires. ◦ Ensure the carrier accepts custom headers on BYE and will route based on them. • If you use a SIP gateway / SBC between LiveKit and the carrier ◦ Configure the SBC/gateway to insert custom headers into the BYE (or to pass through headers originating from your app). ◦ If LiveKit is the SIP endpoint, you’ll need a way to convey the desired headers from your app to the gateway (for example via a control API or setting participant/session metadata that the gateway reads). • If you want LiveKit itself to trigger the BYE with headers ◦ Confirm the signaling component you run supports injecting custom SIP headers on outbound BYE. If not supported, you’ll need a small control/adapter service that: i. Receives the transfer command from your AI logic. ii. Calls the SIP gateway API to send BYE with the required headers. iii. Updates LiveKit participants/metadata so the UI/agent state matches. Self-hosting considerations • Self-hosting is possible, but you must host or integrate a SIP-capable gateway/SBC that can accept or insert custom SIP headers. LiveKit primarily handles real-time media and participants; SIP behavior depends on your gateway or signaling layer. • Ensure your environment can run the gateway and that network/firewall rules allow SIP signaling and media RTP between LiveKit, the gateway, and the carrier. Immediate next steps I can help with • If you tell me which of the 5 questions above fits your architecture, I’ll give step-by-step options tailored to that setup (example SIP headers, where to set them, sample flow). • If you’re using a specific SIP gateway/SBC (name/model), I can suggest how to insert or pass custom headers on BYE for that product. • If you want a small control adapter pattern, I can outline the required API calls and sequence (update participant metadata, call gateway API to send BYE with headers, confirm carrier response). Pick which architecture matches yours (or paste a short diagram of your current flow) and I’ll provide the exact steps and examples you should implement. , with interactive elements
p
Ok so my current setup is call come from pstn to my kamailio that forward it to LiveKit Sip server and then the LiveKit server where room got created and ai agent and all like that now i want when ai agent send BYE it should be go in LiveKit Sip server then it should be go to a Kamailio then only send to carrier not directly and Bypass the Kamailio as well this is the out setup we want so ya thats it help to establish in our self hosted on EKS.
t
Thanks — this is clear and helpful. I’ll walk you through what you need and the recommended approach for your self-hosted EKS setup so the AI agent’s BYE goes LiveKit -> Kamailio -> carrier, with custom SIP headers added. First, one quick question so I give exact commands/config snippets: • Which custom SIP header names/values does the carrier expect on BYE? (Example:
X-Transfer-To: queue123
,
X-Agent-Login: agent42
) High-level plan (what to implement) 1. Ensure your AI agent signals the desire to transfer to your application control plane (not directly sending SIP to the carrier). ◦ The AI should trigger a transfer action in your application (for example: call a control API that will arrange the BYE + headers). 1. Have your application tell LiveKit to update participant/session metadata so the room/UI reflects the transfer (optional but recommended). ◦ Use participant metadata or room state to indicate transfer target, agent presence, etc. 1. Make the SIP BYE flow through LiveKit’s SIP gateway to Kamailio, not directly from the AI. ◦ The BYE must originate from a component that the LiveKit SIP server will relay to Kamailio. That means the BYE should be sent by the LiveKit SIP component (or by a control adapter that calls the SIP gateway API exposed to Kamailio), not by a separate SIP client that bypasses Kamailio. 1. Insert custom SIP headers into the BYE at the point where signaling can be modified. ◦ Two places to add headers: ▪︎ In your application/control adapter before handing the BYE to LiveKit’s SIP gateway (if that gateway accepts and forwards supplied headers). ▪︎ Or in Kamailio (SBC) as it forwards the BYE to the carrier — Kamailio can add or rewrite headers reliably. Recommended architecture for your requirements (self-hosted on EKS) • Keep Kamailio as your signaling front-end for PSTN and as the single source of truth for outbound carrier signaling. • LiveKit SIP server should be behind Kamailio so all external SIP to carrier goes Kamailio -> LiveKit -> Kamailio -> carrier (Kamailio on both ingress and egress can be configured to ensure correct routing). • Use a small control adapter service (can run in EKS) that: a. Receives the transfer command from the AI agent. b. Calls LiveKit to update participant metadata/state (so room/UI reflects the transfer). c. Calls Kamailio’s management API or your SIP gateway API to send a BYE with the required custom headers toward the carrier (so Kamailio is the originator/handler of the carrier-bound BYE). • This avoids bypassing Kamailio and gives you a place to set headers precisely. Where to add the custom headers (two practical options) • Option A — Add headers in Kamailio before sending to carrier: ◦ Kamailio has flexible scripting (cfg) to detect BYE requests and add headers like
append_hf("X-Transfer-To: queue123\r\n");
or
hdr_append()
depending on module. This guarantees headers are injected at the last hop and preserved for carrier routing. ◦ Advantage: centralized control at the SBC level; no dependency on LiveKit supporting header injection. • Option B — LiveKit/gateway accepts headers to forward: ◦ If your LiveKit SIP gateway supports passing through custom SIP headers from application-level control (via an API or session metadata), your control adapter can set the headers and LiveKit will forward them to Kamailio which then forwards to the carrier. ◦ Confirm LiveKit SIP gateway will forward arbitrary BYE headers unchanged; if not, use Option A. Practical sequence (example flow) 1. PSTN -> Kamailio (ingress) -> LiveKit SIP server -> LiveKit room (AI agent). 2. AI agent decides to transfer and calls your control adapter: POST /transfer { participantId, targetQueue, headers: { X-Transfer-To: queue123 } }. 3. Control adapter updates LiveKit participant metadata so UI/agent know call is transferring. 4. Control adapter instructs Kamailio (via management API or by sending a controlled SIP BYE through your SIP gateway) to send BYE to the carrier. Kamailio injects the custom headers and forwards to carrier. 5. Carrier routes to queue/agent per header. Once carrier connects, update LiveKit participants/state so the UI switches to agent audio. EKS specifics and deployment notes • Run Kamailio as a StatefulSet or Deployment with stable networking and necessary SIP ports open (UDP/TCP/WS/TLS depending on transport). • Ensure NAT, RTP, and firewall rules allow media between LiveKit pods and Kamailio and between Kamailio and carrier. • Run the control adapter as a Deployment with a secure API endpoint the AI can call. • Use ConfigMaps/Secrets for Kamailio cfg and any credentials needed to call carrier APIs. • For reliability, use health checks and configure SIP transaction timers inside Kamailio to match carrier expectations. Validation and testing steps 1. Test header injection locally: have Kamailio log outgoing BYE headers to verify
X-
headers are set. 2. Simulate AI transfer flow: trigger the control adapter to perform the sequence and trace SIP messages with sngrep or tcpdump on Kamailio to confirm BYE passes through with custom headers. 3. Confirm carrier behavior in a staging trunk before production. Next action I can take for you • If you share the exact header names/values, I can give a sample Kamailio config snippet to append headers on BYE. • If you prefer LiveKit to carry headers, tell me whether your LiveKit SIP gateway exposes a control API or session metadata channel; I’ll outline the exact API calls you need. • If you want the control adapter pattern, I can provide a minimal sequence and sample pseudo-API for your service to implement. Tell me which option you prefer (Kamailio header injection vs LiveKit-forwarded headers) and the header names you need, and I’ll produce the specific Kamailio config or control-adapter sample. , with interactive elements
p
• Option B — LiveKit/gateway accepts headers to forward: ◦ If your LiveKit SIP gateway supports passing through custom SIP headers from application-level control (via an API or session metadata), your control adapter can set the headers and LiveKit will forward them to Kamailio which then forwards to the carrier. ◦ Confirm LiveKit SIP gateway will forward arbitrary BYE headers unchanged; if not, use Option A. How to setup this like what changes in trunk inbound or what other configuration changes and it is possible or not
t
Thanks — this is very helpful context. I’ll respond to the specific question you asked: whether LiveKit’s SIP gateway can forward arbitrary BYE headers and what trunk/inbound changes are required — and what I need from you to give exact steps. Quick summary of what I’ll do next • I need a few details about your LiveKit/Kamailio setup to confirm if LiveKit can forward BYE headers unchanged. • If LiveKit can’t forward them, I’ll provide a concrete Kamailio configuration snippet (Option A) and an exact control-adapter flow you can run on EKS. Please answer these specific questions so I can give precise configuration steps: 1. LiveKit version and SIP gateway ◦ Which LiveKit release are you running? ◦ Are you using LiveKit’s built-in SIP gateway or a separate SIP gateway component that connects LiveKit - Kamailio? 1. SIP transport between LiveKit and Kamailio ◦ How is LiveKit connected to Kamailio (UDP, TCP, TLS, or SIP over WebSocket)? ◦ Is Kamailio configured as a proxy for both ingress and egress PSTN traffic (PSTN -> Kamailio -> LiveKit -> Kamailio -> PSTN)? 1. BYE originator in the desired flow ◦ In your ideal flow, who should create the BYE that goes to the carrier: LiveKit SIP gateway, Kamailio, or your control adapter/service? 1. Existing Kamailio header handling ◦ Does your current Kamailio config rewrite, strip, or whitelist SIP headers on BYE? If you’re unsure, can you share the relevant part of your Kamailio cfg that handles outbound requests or BYE routing? 1. Carrier header requirements ◦ Exact header names and example values your carrier expects (for example:
X-Transfer-To: queue123
,
X-Agent-Login: agent42
). ◦ Any required header formatting, or whether the carrier requires these headers only on BYE (vs other methods). 1. Control API availability ◦ Does your LiveKit SIP gateway expose any control API or session metadata channel that your control adapter can call to attach SIP headers to outbound SIP messages? If yes, which API? 1. SIP trace/testing access ◦ Can you run sngrep/tcpdump on Kamailio to capture SIP traces for a test call and share a redacted BYE trace? This helps confirm whether LiveKit currently forwards BYE headers. 1. Deployment/security constraints ◦ Any compliance/security constraints that would prevent adding arbitrary headers at Kamailio or LiveKit (for example, header whitelists, logging policies, or carrier restrictions)? If you prefer, start with the header names/values (question 5) and the answer to who should originate the BYE (question 3). With those two I can immediately produce: • A sample Kamailio snippet to append headers on BYE (Option A). • A sample control-adapter flow and the exact places to call LiveKit/Kamailio APIs if you want Option B and it’s supported. Pick one of: • Send header names + BYE originator now and I’ll provide the config snippet and control flow. • Or provide answers to all questions above and I’ll produce step-by-step EKS deployment and trunk/inbound changes for your exact environment., with interactive elements
p
1. LiveKit version and SIP gateway 2. Image:
livekit/sip:latest, helm repo add livekit <https://helm.livekit.io>
we use helm repo or chart for livekit and update our configuration file like that currently we do 3. Type: Using the standard LiveKit SIP gateway component deployed as a separate
sip-server
service within the EKS cluster. 4. SIP transport between LiveKit and Kamailio 5. Protocol: Internal communication between Kamailio and LiveKit is handled over UDP/TCP on port 5060. 6. Proxy Flow: Kamailio acts as the entry/exit point: Five9 (TLS 5061) ↔️ Kamailio ↔️ LiveKit (UDP 5060). 7. BYE originator in the desired flow 8. Current: The
ai-agent
triggers a room deletion via the LiveKit API, which causes the LiveKit SIP Gateway to generate the
BYE so currently BYE generated in Sip server and its directly send to carrier thats happend but also no any custom header i see in tcpdump or sngrep when i do in the sip server pod
. 9. Requirement: The
BYE
must traverse Kamailio to ensure it reaches Five9 via the correct Elastic IP (EIP) and TLS transport. 10. Existing Kamailio header handling 11. Mechanics: Kamailio uses
record_route_preset
with double Record-Route headers (one for the external EIP and one for the internal pod IP) to force the SIP path. 12. Filtering: It has an
OPTIMIZE_HEADERS
route prepared for stripping/whitelisting, and it manually rewrites the
Contact
header in both directions to maintain the signaling path through Kamailio. 13. Carrier header requirements 14. Headers: Five9 expects specific data for transfers (e.g.,
five9RouteType
,
five9RouteValue
). 15. Mapping: The agent sets these as participant attributes in LiveKit, which the SIP gateway maps to custom SIP headers (e.g.,
X-Five9-Route-Type
) on the
BYE
message. 16. Control API availability 17. API: The system uses the LiveKit Server SDK (Python) to dynamically update participant metadata and signal call termination/transfers. 18. SIP trace/testing access 19. Tooling:
sngrep
and
tcpdump
are available on the Kamailio pods to capture and verify SIP message flow and header integrity. 20. Deployment/security constraints 21. Environment: EKS-based deployment with
hostNetwork: true
for predictable SIP routing. Addressing: Uses AWS Elastic IPs (EIPs) mapped via an NLB to provide stable public entry points for Five9.
t
Thanks — this is very clear. You already have the right architecture: the LiveKit SIP server generates BYE, Kamailio must be the hop that forwards to Five9 (so it uses the EIP/TLS), and you want LiveKit to map participant attributes into X-* headers on BYE. That is possible using LiveKit’s attributes-to-headers mapping; below are concrete, practical steps and examples tailored to your EKS + Kamailio flow, plus verification and troubleshooting tips. Quick summary • Feasible: Yes. LiveKit can map participant attributes into SIP headers on BYE and emit them; Kamailio can preserve/forward or modify those headers before sending to Five9. • Key constraint: Kamailio must remain the final egress client to Five9 (so BYE traverses Kamailio and goes out via the EIP/TLS). Ensure Kamailio does not strip the custom headers. • Two places to ensure headers are present: 1) LiveKit mapping (application-level) and 2) Kamailio’s OPTIMIZE_HEADERS route (SBC-level) to pass/whitelist them. What you need to change/verify (step-by-step) 1) LiveKit: Add attributes_to_headers mapping for your SIP trunk • Add the mapping in your trunk config so LiveKit converts participant attributes into SIP headers when it generates BYE. • Example (pseudo/Python-like to match your SDK usage):
Copy code
trunk_config = api.SIPInboundTrunkInfo(
    name="Five9-Trunk",
    numbers=["+your_number"],
    attributes_to_headers={
        "five9.route.type": "X-Five9-Route-Type",
        "five9.route.value": "X-Five9-Route-Value"
    },
    # other trunk settings...
)
• Behavior: When a SIP participant attribute such as
five9.route.type
is present on the SIP participant, LiveKit will include
X-Five9-Route-Type: <value>
on generated BYE messages. 2) AI agent / control flow: set participant attributes before terminating • Before you delete the room / end the call, set the participant attributes via the LiveKit Server SDK:
Copy code
await participant.set_attributes({
  "five9.route.type": "transfer",
  "five9.route.value": "supervisor_queue"
})
# Then delete the room (or call the API that triggers BYE)
await api.room.delete_room(api.DeleteRoomRequest(room=room_name))
• Confirm attributes are attached to the SIP participant (you can log attribute changes or subscribe to participant attribute events). 3) Ensure LiveKit’s SIP gateway respects Kamailio’s Record-Route path • You already have double Record-Route in Kamailio which forces responses to traverse Kamailio. Ensure LiveKit’s SIP server does not strip Record-Route and will honor it. • Keep LiveKit SIP settings so signaling_ip/sip_port match your internal Kamailio endpoint (UDP/TCP 5060). In Helm values, ensure sip.port and signaling/network settings reflect your cluster networking. 4) Kamailio: whitelist/pass X-* headers and preserve routing • Kamailio’s OPTIMIZE_HEADERS route must allow X-Five9 headers and not strip them. Update header whitelisting or add explicit header append logic if needed: ◦ If Kamailio strips unknown headers, add rules to preserve
X-Five9-Route-Type
and
X-Five9-Route-Value
. ◦ If you want to assert values or add/modify them at the last hop, do that here so Five9 sees the expected names/values. • Example: in the BYE handling path (cfg), ensure you do not remove X-* headers and that you call t_relay() so BYE follows the recorded route:
Copy code
if (is_method("BYE")) {
    if (loose_route()) {
        # Keep custom X-* headers
        route(OPTIMIZE_HEADERS);  # ensure this doesn't strip X-Five9-*
        t_relay();
    }
}
• If OPTIMIZE_HEADERS strips custom headers by default, explicitly append them:
Copy code
append_hf("X-Five9-Route-Type: ${hdr(custom_attr)}\r\n");
(Use your actual variable/logic to build values.) 5) Ensure BYE leaves Kamailio to Five9 over TLS/EIP • Confirm Kamailio selects the outbound route that uses your EIP/NLB -> Five9 TLS 5061 path. Your double Record-Route approach should force responses through Kamailio; verify routing table and lookup logic selects the TLS next hop. • If needed, route selection can be forced by matching topmost Record-Route and using t_on_branch or next_hop selection logic. 6) Testing & verification (recommended order) • Step A — Attribute propagation check: ◦ Set attributes on the SIP participant and inspect LiveKit’s internal state or logs to confirm attributes exist before termination. • Step B — Trigger BYE from LiveKit and capture on Kamailio: ◦ On Kamailio pod run: sngrep or tcpdump and filter BYE to confirm LiveKit’s BYE arrives at Kamailio with X-Five9-Route-* present. ◦ Example sngrep commands: ▪︎ sngrep -c "BYE" -H "X-Five9" ▪︎ tcpdump -i any -s 0 -A port 5060 | grep -A 10 "BYE" • Step C — Confirm Kamailio forwards BYE to Five9 over TLS (port 5061) and that Five9 receives the X-* headers: ◦ Capture on Kamailio egress interface or on your NLB logs (if available). • Step D — End-to-end: Ensure Five9 behavior (queue/transfer) is triggered by the header values. 7) Common issues and how to resolve them • Missing headers at Kamailio: verify LiveKit mapping is configured correctly and that attributes are actually set on the SIP participant before the BYE. • Kamailio strips headers: update OPTIMIZE_HEADERS or routing cfg to whitelist
X-Five9-*
. • BYE bypasses Kamailio and goes directly out: ensure Record-Route sequencing and that LiveKit does not choose an alternate route. Double-check the Via/Record-Route stack in a SIP trace — BYE should have the Kamailio Record-Route entries. • Transport mismatch (UDP vs TLS): LiveKit sends to Kamailio UDP 5060; Kamailio must translate/relay to Five9 TLS 5061. Ensure Kamailio’s t_relay selects the TLS socket for that destination. 8) Sample validation sequence you can run now 1. On a test call, set participant attributes: ◦
five9.route.type=transfer
◦
five9.route.value=supervisor_queue
1. Trigger the room deletion so LiveKit generates BYE. 2. On Kamailio pod: ◦ Run sngrep/tcpdump and capture the incoming BYE from LiveKit. Confirm BYE contains X-Five9 headers. ◦ Confirm kamailio forwards BYE to Five9 over TLS 5061 and that headers are present in the outbound packet. 1. If headers are missing outbound, inspect OPTIMIZE_HEADERS and any rewrite logic that touches BYE/Contact/Record-Route. If you want, I can provide: • A specific Kamailio cfg snippet to ensure X-Five9 headers are preserved and t_relay to TLS is used. • A short LiveKit Helm values YAML example for sip config fields you should verify. • A minimal control-adapter example (if you want Kamailio to add or override headers instead). Which of the following would you like next? • Kamailio cfg snippet to preserve and/or append X-Five9 headers on BYE. • LiveKit Helm values snippet showing the relevant sip settings (signaling_ip, sip_port, and a reminder where to add attribute->header mapping). • Both snippets together and a short checklist for your staging test. Tell me which snippet(s) you want and I’ll produce them with exact lines you can paste into your configs. Sources: SIP Lifecycle Management Agent | LiveKit Documentation, with interactive elements