On a configuration project,
dev runs the managed loop in process on a loopback listener. instructions.md, agent.json and the tools file when agent.json points at one are watched and reloaded on save, a set from another terminal included. With web set as dev starts, the chat page is served at http://127.0.0.1:8787/web; the page’s title, greeting, number and voice button are read as dev starts, so a web or phone change needs a restart, and so does an edit to .env. On an agent with a number or voice settings that page has a voice button: the dev listener answers a WebSocket on the conversation’s path, runs the agent’s voice loop (the greeting, voice.bargeIn, keypressInterrupts, stt and tts from agent.json, Telnyx recognition and synthesis with the same credentials as the model) and journals each exchange into the conversation; one line per turn is printed here. The local loop waits for the confirmed end of turn and runs the direct engine, so voice.eager, voice.filler and voice.harness apply only on a deployed call. invoke, chat and rpc reach the listener with --local; dev records where it listens in .telnyx/dev.json, which --local reads, so those run in the same project directory. dev needs a session or TELNYX_API_KEY in .env to reach the model, and the --local callers need no sign-in. It admits one dev per project.
On a code-based project, dev writes .telnyx/ as deploy would and hands over to telnyx-edge dev, the local actor stack in Docker, with the class reloaded on save. That stack keeps running after Ctrl-C; docker compose -f .telnyx/dev/compose.yaml down stops it.
Calls on a phone number, texts, email and memory need a deploy; the page’s voice button is the one way to speak to the agent locally. Local Development has what runs where and what works locally.