feat: add edge-customer-agent-typescript example (DEV-839) - #99
Open
somemothersson wants to merge 3 commits into
Open
feat: add edge-customer-agent-typescript example (DEV-839)#99somemothersson wants to merge 3 commits into
somemothersson wants to merge 3 commits into
Conversation
somemothersson
requested review from
harpreetTelnyx and
ireither
as code owners
August 10, 2026 23:46
Durable Entity Agent on Telnyx Edge Compute — one actor per customer phone number, surviving across days, calls, SMS, and evictions. The AI Assistant is the reasoning harness inside; the Agent SDK owns the durable entity. - Register in examples_mapping.yaml (product: voice, lang: typescript) - Add row to README.md Voice AI table (148 -> 149) - verify.py already supports telnyx.toml edge marker (no changes needed) - Passes python scripts/verify.py --only edge-customer-agent-typescript - Passes tsc --noEmit
…-839)
Three fixes discovered during Edge Compute deploy + smoke test:
1. telnyx.toml: declare each secret with its own [[secrets]] block
(binding=name=SECRET_NAME). The runtime aggregates them into
env.SECRETS.get('NAME'). The old single-binding block was rejected
by 'telnyx-edge ship'.
2. customer-agent.ts: replace process.env['X'] with
await this.env.SECRETS.get('X') — the Edge runtime exposes secrets
via the Secrets interface, not process.env. Made getLLM() and
getSalesforce() async. Added normalizePhone() helper to restore
the '+' prefix that Dapr's RFC 1123 naming forbids in actor names.
3. index.ts: added actorNameFromPhone() to strip the leading '+'
from E.164 numbers before idFromName(). Dapr reminder/alarm names
must be lowercase alphanumeric per RFC 1123 — the '+' caused
ERR_ACTOR_REMINDER_DELETE on every actor method call.
Smoke test: 8/8 endpoints pass on deployed Edge Compute function.
https://edge-customer-agent-typescript-93b6ca4c-6.telnyxcompute.com
somemothersson
force-pushed
the
feat/edge-customer-agent-typescript
branch
from
August 13, 2026 17:47
02eb1ca to
163d7bf
Compare
Real Telnyx TeXML Application webhooks arrive as application/x-www-form-urlencoded with PascalCase fields (From, To, CallControlId, CallDuration, Body). The original handlers called req.json() which would throw on form-encoded bodies, breaking real inbound calls. Add parseWebhookBody() helper that normalizes both formats into a common shape: form-encoded TeXML (PascalCase) and JSON Call Control API (nested data.payload with snake_case). The voice and call-ended webhook handlers now use this helper instead of req.json() directly. Discovered during end-to-end telephony testing: wired +19362204906 to the deployed edge function via a TeXML Application, placed test calls, confirmed the voice webhook fires with form-encoded bodies.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Durable Entity Agent on Telnyx Edge Compute — one actor per customer phone number, surviving across days, calls, SMS, and actor evictions. The AI Assistant is the reasoning/voice harness inside the agent; the Agent SDK owns the durable entity.
Key insight (Ian Reither, Aug 10): "The Assistant isn't the durable object. Ian is." The actor IS the customer — not a conversation, not a session. A durable entity that lives across channels (voice/SMS/WhatsApp), across days, across interactions. No external state machine. No queue infrastructure. No context reconstruction.
Why
Existing edge-* examples (Python/Node/Go) demonstrate Edge Compute functions. This is the first TypeScript example showing the Agent SDK pattern: a -bound actor that addresses a customer by E.164 number via and persists state across interactions. It unblocks the same pattern for any TS developer building durable customer-facing agents on Telnyx Edge Compute.
Changes
edge-customer-agent-typescript/— new self-contained example (TypeScript, ESM)src/customer-agent.ts—CustomerAgent extends Agent<Env, CustomerState>; keyed by E.164, durable across evictionssrc/index.ts— fetch handler wiring inbound voice + SMS to the actorsrc/llm.ts,src/messaging.ts,src/voice.ts,src/salesforce.ts,src/state.ts— supporting modulestelnyx.toml—[[actors]]binding (Agent SDK manifest, notfunc.toml)package.json(type: module,@telnyx/edge-runtime),tsconfig.json,.env.example,README.md,GUIDE.md,API.mdscripts/examples_mapping.yaml— registeredge-customer-agent(product: voice, language: typescript, framework: edge-compute)README.md— add row to Voice AI table (148 → 149 examples)Verification
python scripts/verify.py --only edge-customer-agent-typescript --verbose→ PASS (0 errors)npx tsc --noEmit→ 0 type errorsverify.pyalready supports thetelnyx.tomledge marker (added byedge-agri-crop-advisoryon main); noverify.pychanges needed in this PR.Linear
Refs DEV-839.