add reopens the wizard over this project’s agent.json, pre-filled, and asks again about the model, the numbers, email, the channels, the browser page, the greeting and voice, memory and the step limit. It needs a terminal. Each add <thing> below is the non-interactive form. Every form edits agent.json (phone, email, web, channels, tools or secrets), the next deploy applies the change, and a running dev reloads it, except web and phone, which the page reads as dev starts.
Phone
add checks the format; the number must be in the account by the time of the next deploy, which looks it up and stops if it is missing. The next deploy puts it on a Call Control application for calls and a messaging profile for texts, and Phone follows what happens from there.
deploy finds or creates the inbox, subscribes its domain to email.received and prints the address.
Web
<mount>/web and an embed script at <mount>/web/embed.js for any site; without web, /web answers 404. The page is public once deployed: anyone with the URL can talk to the agent, and nothing on the page asks who they are. --title is the page’s title and the launcher’s label, the agent’s name with dashes and underscores as spaces by default. When the agent has a number, the page’s header shows it as a tel: link. When it has a number or voice settings, the page under telnyx-acp dev also has a voice button: the browser becomes the media stream (µ-law at 8 kHz, the same protocol as a call) and the exchange lands in the chat as bubbles; the deployed page does not offer that yet. dev serves the page from its next start; a dev already running needs a restart.
Channel
call_control_application, texml_application, messaging_profile or email_domain, and never touches a number. The next deploy points the artifact’s webhook at the function and remembers the previous one. Channels follows what happens from there.
Tool
web_search is Web Search as web_search, fetch_page and, with --research, research; it runs over the account’s credential, so nothing to add. mcp --url is a remote MCP server: the CLI lists its tools and writes them into agent.json, and the model sees them as <name>__<tool>; --secret NAME authenticates (a bearer token, or --header X-API-Key to send it in that header), with the value read from .env here and from the platform secret once deployed. agent_gateway --id declares a gateway instance; the managed loop does not call a gateway’s tools yet, so the entry is recorded for when it does. Web Search, MCP Servers and Agent Gateway have each flag; telnyx-acp tools lists what the model has.
Secret
add secret prompts for the value, or reads it from stdin when piped, and agent.json records only the name. No value ever belongs in a file in the project or on a command line, and the error for a rejected secret names the secret, never its value. .env holds keys for dev, and the secret of an MCP server when add tool mcp or tools --refresh lists its tools; it is never read on the platform. The scaffolded .gitignore excludes .telnyx/ and node_modules/, and .env belongs in it before the first commit.
Some secrets have a meaning of their own.
TELNYX_PUBLIC_KEYis the account’s public key. The function verifies every webhook’s signature over the raw body against it before parsing the body, and answers 401 without it, so a project with a phone number, an email inbox or a channel must have it.deployasks for it once.OPENAI_API_KEY,ANTHROPIC_API_KEY,GOOGLE_API_KEYandGROQ_API_KEYare sent as the caller’s key for anopenai/*,anthropic/*,google/*orgroq/*model, and a class reads them withenv.SECRETS.get("OPENAI_API_KEY").