Inbound Activation
Overview
Inbound activation is the process of linking an agent to a phone number so it can receive inbound calls. This is a customer-level operation that configures the runtime resolution system.
Activation Flow
- Customer selects a phone number with inbound capability
- Customer selects an agent to handle inbound calls on that number
- Backend links the agent to the number
- From this point, inbound calls to that number route to the linked agent
Agent.inboundPhoneNumber Field
{
// On the Agent document
inboundPhoneNumber: string // E.164 format, unique sparse index
}- E.164 format: Always stored with
+prefix (e.g.,+15551234567) - Unique sparse index: Only one agent can be linked to a given number; null values are not indexed
- This field is the runtime resolution key the Python agent uses this to find which agent config to load
PhoneNumberAssignment.inboundConfig
{
inboundConfig: {
dispatchRuleId: string, // LiveKit dispatch rule ID (copied from SIPTrunk)
defaultAgentId: string, // Agent UID linked for inbound calls
isActive: boolean // Whether inbound is currently active
}
}This is stored on the customer's PhoneNumberAssignment doc and used for admin display and management.
Dual Storage Pattern
| Storage Location | Purpose | Used By |
|---|---|---|
Agent.inboundPhoneNumber | Runtime resolution | Python agent (via /internal/resolve-inbound-number) |
PhoneNumberAssignment.inboundConfig | Admin UI display & management | Frontend dashboard |
Both are updated together during activation/deactivation to maintain consistency.
Auto-Resolution
When the frontend sends an activation request, it may send an assignmentUID that points to an outbound assignment. The backend handles this gracefully:
- Receives
assignmentUID(may be outbound-direction assignment) - Looks up the phone number from that assignment
- Finds the inbound-capable assignment for the same phone + org + customer
- Applies the inbound activation to the correct assignment
This allows the UI to work with whatever assignment reference it has without needing to know about direction-specific assignment docs.
Deactivation
When inbound is deactivated for a number:
- Agent link cleared:
Agent.inboundPhoneNumberis set tonull - Config deactivated:
PhoneNumberAssignment.inboundConfig.isActiveset tofalse - Trunk/dispatch NOT deleted: The inbound trunk and dispatch rule remain intact on LiveKit
The trunk and dispatch rule stay alive because:
- They may be shared infrastructure
- Reactivation should be instant (no need to recreate LiveKit resources)
- The number might be reassigned to a different agent later
Number Removal / Unassignment
When a number is unassigned from an org or removed from a trunk (but the trunk itself remains):
- Agent link cleared: Same as deactivation
- Assignment records deleted/downgraded:
PhoneNumberAssignmentdocs removed or direction downgraded - Dispatch rule NOT deleted: The dispatch rule is a trunk-level shared resource it is only deleted when the trunk itself is deleted
- Number removed from LiveKit trunk: The number is removed from the inbound trunk's allowed numbers list via
updateSipInboundTrunkFields
The dispatch rule is never deleted during per-number operations because:
- One dispatch rule serves all numbers on a trunk
- Deleting it would break inbound routing for all other numbers on the same trunk
- It is only cleaned up when the entire trunk is deleted or by the
trunkSyncorphan cleanup
Constraints
| Constraint | Enforcement |
|---|---|
| One agent per inbound number | Agent.inboundPhoneNumber unique sparse index |
| One inbound customer per number | Inbound exclusivity rule in assignment system |
| Customer must have inbound assignment | Cannot activate without inbound-direction assignment |
| Direction hierarchy | Customer's org must also have inbound access |