> ## Documentation Index
> Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# encodeAgentName()

> **encodeAgentName**(`name`): `string`

Encode a routing name into the actor id that addresses its instance.

An actor id is not free-form. It is a path segment on every call to the
instance, it is folded into the persistent records the instance owns, and it
names the instance's timers — and only ASCII letters, digits, `-`, `_`, and
`.` survive all three. An id built from anything else is not merely ugly: it
cannot be addressed, and the instance never activates.

Names customers actually route on are not confined to that set — a phone
number (`+15550100`), an email address, a composite key, a name with accents
or emoji. This encoder maps any such name onto the addressable set, and back
again:

```ts theme={null}
encodeAgentName("alice");        // "alice"          (already addressable — unchanged)
encodeAgentName("case-42");      // "case-42"        (already addressable — unchanged)
encodeAgentName("v1.2.3");       // "v1.2.3"         (already addressable — unchanged)
encodeAgentName("+15550100");    // ":2b:15550100"
encodeAgentName("a/b");          // "a:2f:b"
encodeAgentName("user@ex.com");  // "user:40:ex.com"
encodeAgentName("café-☕");       // "caf:c3a9:-:e29895:"
```

**The scheme**

Each run of characters outside the addressable set becomes `:` + the
lowercase hex of that run's UTF-8 bytes + `:`. Characters inside the set are
written through untouched. `:` itself is never written through — it is
always escaped (`:` → `:3a:`) — which is what makes an escape impossible to
confuse with an ordinary name and the encoding reversible by
[decodeAgentName](/docs/agent-sdk/internals/mount/decodeAgentName).

Two names therefore never share an id: the id says exactly which characters
were escaped, so it decodes back to one name and one name only.

**How long a name may be**

The limit is on the ID once URL-escaped, not on the name: an actor id may
occupy at most [MAX\_ESCAPED\_ACTOR\_ID\_LENGTH](/docs/agent-sdk/limits#max_escaped_actor_id_length) characters escaped, and a
name whose id would be longer is refused here rather than handed back as an
id the platform cannot keep an instance under.

**So how many characters of name fit depends on which characters they are**,
because an escape is longer than what it replaces — two hex digits per UTF-8
byte, plus the two `:` bracketing each run, which cost three apiece once
URL-escaped:

```ts theme={null}
encodeAgentName("a".repeat(225));  // 225 characters in, 225 out — the most a name can be
encodeAgentName("☕".repeat(36));   // 36 in, 218 out, 222 escaped — inside the limit
encodeAgentName("☕".repeat(37));   // throws: 228 escaped characters of id
```

An all-ASCII name (letters, digits, `-`, `_`, `.`) gets the full 225, since
it passes through unchanged and has nothing to escape. Everything else costs
more: 4 characters per accented Latin letter (54 of them fit), 6 per
three-byte character such as `☕` or most CJK (36 fit), and 8 per emoji or
other astral character (27 fit), with a further 6 for each separate run of
them. Budget for the characters your names actually use, use
[escapedActorIdLength](/docs/agent-sdk/limits#escapedactoridlength) when you need the exact number, and prefer
catching the throw over assuming a name fits.

**This encoding is part of an actor's identity, and is frozen**

The id an instance is first addressed by is the id its persistent state, its
timers, and every later request are filed under. **Changing how a name
encodes re-points that name at a different, empty instance and orphans
everything the old one held.** Treat the mapping as fixed for the lifetime
of the deployment: the same name must always yield the same id. It will not
be changed under you, and you should not re-derive it — call this function
instead.

That is also why [mountAgents](/docs/agent-sdk/internals/mount/mountAgents) applies it to every name it resolves: a
mounted agent needs no encoding code, and a hand-written front door that
addresses the SAME instances stays in step by calling this rather than
writing the rule out again.

Names already inside the addressable set pass through byte-for-byte, so
adopting the encoder never re-points an instance that was already reachable.

**Two things to get right**

Takes the RAW name, **exactly once**. Encoding an already-encoded name
escapes its `:` signs (`":2b:15550100"` → `":3a:2b:3a:15550100"`) and
addresses a different instance — pass the name as the caller wrote it, not a
value read out of a URL path without decoding it first.

Letter case is significant: `Alice` and `alice` are different names and
different instances. Lowercase your names before you route on them if you
mean them to be the same.

**Parameters**

| Parameter | Type | Description |
| - | - | - |
| `name` | `string` | The routing name, decoded — the value a caller means, not a URL-encoded form of it. |

**Returns**

`string`

The actor id for that name, built only from ASCII letters, digits,
`-`, `_`, `.`, and `:`.

**Throws**

`TypeError` when the name has no faithful id and encoding it would
hand back one that cannot be addressed: an empty name, one whose id would
occupy more than [MAX\_ESCAPED\_ACTOR\_ID\_LENGTH](/docs/agent-sdk/limits#max_escaped_actor_id_length) characters once escaped
(which a name of more than that many characters always does), or one
containing an unpaired surrogate. The message names the offending input and
the limit it missed.
