Recipes← all recipesView on GitHub

Give an AI agent a SIP address

AI AgentsSIP URI for a voice AI agent

Create a SIP address that rings a hosted AI agent, so a SIP phone or PBX can reach it without a phone number in between.

restsip

The claim

A hosted resource is reachable two ways: by a phone number pointed at it, or by a SIP address. This recipe makes the second one. The response carries the uri, and that string is the whole integration on the PBX side.

Why it holds

The vendored REST spec, tools/openapi/rest.json, is the authority.

  • POST /api/fabric/sip_addresses requires name and calling_handler_resource_id. The name is “lowercase letters, numbers, and hyphens only” and “is used to build the address’s SIP URI”. The recipe refuses anything else before sending.
  • user defaults to *, which “accepts any username”. Set it when the PBX should reach the agent by one specific username.
  • encryption is required, optional or forbidden. The recipe asks for required.
  • codecs defaults to PCMU and PCMA, and ip_auth_enabled to false. The recipe leaves both alone.

Neither SDK wraps this path in the versions pinned here. The request goes through the HTTP client every namespace shares, as the subproject recipes do.

How it works

NAME_SHAPE = re.compile(r"^[a-z0-9-]+$")

def give_address(resource_id, name, user=None, encryption="required"):
    if not NAME_SHAPE.match(name):
        raise ValueError(...)
    body = {"name": name, "calling_handler_resource_id": resource_id,
            "encryption": encryption}
    if user:
        body["user"] = user
    return http.post("/api/fabric/sip_addresses", body=body)

What the platform receives:

{"name": "front-desk",
 "calling_handler_resource_id": "0b7a2f3e-9c41-4d6e-8a52-1f0e3d2c4b5a",
 "encryption": "required"}

The response’s uri is what you dial. Its context says which domain the address lives under, public for the project’s default. With the default user, any username at that domain reaches the agent. With user set, only that one does.

Limitations

The verifier proves the request, not the call. Whether a given PBX accepts the URI, negotiates SRTP and reaches the agent is live behaviour.

password is write-only and never returned. A registration password belongs in your secrets, not in this recipe’s arguments.

What to change first

Change encryption="required" to "always" and run the verifier. The exact body comparison fails on a value outside the enum, which is the point. Three values are the whole vocabulary.