---
title: "Set or clear this address's own action or actor"
method: PUT
path: "/v1/projects/{project_id}/addresses/{identifier}"
tags: ["Channels"]
---

# Set or clear this address's own action or actor

`PUT /v1/projects/{project_id}/addresses/{identifier}`

## Request

- Base URL: `https://api.naturali.ai`
- URL: `https://api.naturali.ai/v1/projects/{project_id}/addresses/{identifier}`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.naturali.ai/authorize`, token URL `https://api.naturali.ai/token`, scopes: `mcp:access`)

Upserts the address with its `action`, the actor it speaks as, or both; a field left out is left alone. `action: null` forgets the exception and defers back to the route table; any other `action` requires the same fields a route or channel default would (`agent_id` for `agent`, `text` for `message`).

`actor_id` binds an actor of this project, so the address speaks as the same actor your own sessions use. A changed actor deletes the address's conversations and their sessions — a session's actor is fixed — and the next message opens a fresh one; the actor naturali created for the address is deleted with them. An actor you bind is never deleted here.

## Request body

- AddressActionSet: At least one of `action` and `actor_id`. `action` is one of `agent` / `oneshot` / `message` / `silence`, or `null` to clear it. `agent_id` is required when it is `agent`, `text` when it is `message`; `repeat` is only valid alongside `action: message`.
  - `actor_id` string, nullable: An actor of this project for the address to speak as, `404` when the project has none by that id. Create it with your own user id as its `external_id`: every tool call in the address's sessions carries that actor's `actor_id` and `actor_external_id` as tool context, set by the runtime and never by the caller, so a tool knows which of your users is talking. `null` releases a bound actor (kept, not deleted); the next message gets an actor naturali creates.
  - `action` 'agent' | 'oneshot' | 'message' | 'silence' | 'null', nullable: What an inbound message becomes. `agent` is a dialogue: the identity behind the message gets a session, and every later message on it continues the same one. `oneshot` runs the agent once and keeps nothing — no address, no actor, no session, no conversation — so each message is answered on its own. Choose it for work that is filed rather than discussed; choose `agent` when the answer depends on what came before. `message` delivers fixed text without running an agent, and `silence` answers nothing.
  - `agent_id` string
  - `text` string
  - `repeat` union
    - 'every' | 'once'
    - object
      - `after_seconds` integer, required
  - `language` string
  - `config` object: Conversation config bag — media handling, persona overrides, the Discord allowlist, and how a `oneshot` answers. `discord.reply` picks the delivery: `react` (the default) adds `discord.reaction` — `\u2705` unless named — to the message that triggered the run, `mention` answers beside it addressing whoever asked, `react_or_mention` reacts when the agent writes nothing and answers like `mention` when it writes a line, `thread` opens a thread and answers inside it, and `none` delivers nothing at all. A run that fails delivers nothing in every mode, so a reaction always means the work was done; there is no failure marker. A mention with nothing else in it is ignored unless the action says otherwise, for any action. `discord.use_replied_message: true` takes the text of the message it replies to, so replying to a message with only the mention files that message. `discord.empty_mention_text` answers any other bare mention with that fixed text, addressing the sender, without running the agent. `discord.forward_user_id: true` hands the sender's Discord user id to the agent's tools as the `discord_user_id` tool context, which a tool's `headers` read as `{{context:discord_user_id}}`. It is the id Discord reported for the message's author, never text the model wrote, so a tool can act for whoever sent it. Off unless set, because tool context reaches every tool the agent has. Read only for `oneshot`. A conversational `agent` in a guild *is* its thread — that is what its session is keyed on — so it always opens one.
  - `display_name` string: Set only when the address is created by this call.

## Response `200`

Action updated.

- Address: What an inbound message resolves to — a channel's `default`, a route, or an address's own action, one shape on all three. For a Discord channel, `config.discord.allowed_role_ids` / `allowed_user_ids` restrict who may invoke the agent in a server — either list admits, empty or absent lists mean everyone, decided before the agent is invoked so an unlisted member costs nothing.
  - `action` 'agent' | 'oneshot' | 'message' | 'silence' | 'null', nullable, required: What an inbound message becomes; `null` only on an address with no action of its own, which the route table then decides. `agent` is a dialogue: the identity behind the message gets a session, and every later message on it continues the same one. `oneshot` runs the agent once and keeps nothing — no address, no actor, no session, no conversation — so each message is answered on its own. Choose it for work that is filed rather than discussed; choose `agent` when the answer depends on what came before. `message` delivers fixed text without running an agent, and `silence` answers nothing.
  - `agent_id` string, nullable, required: The agent that answers, when `action` is `agent` or `oneshot`.
  - `text` string, nullable, required: The fixed text delivered, when `action` is `message`.
  - `repeat` union, required: How often a `message` fires: `every` (default), `once`, or `{ after_seconds }`. Null unless `action` is `message`.
    - 'every' | 'once'
    - object
      - `after_seconds` integer, required
  - `language` string, nullable, required: Preferred reply language; null lets the agent decide.
  - `config` object, nullable, required: Conversation config bag — media handling, persona overrides, the Discord allowlist, and how a `oneshot` answers. `discord.reply` picks the delivery: `react` (the default) adds `discord.reaction` — `\u2705` unless named — to the message that triggered the run, `mention` answers beside it addressing whoever asked, `react_or_mention` reacts when the agent writes nothing and answers like `mention` when it writes a line, `thread` opens a thread and answers inside it, and `none` delivers nothing at all. A run that fails delivers nothing in every mode, so a reaction always means the work was done; there is no failure marker. A mention with nothing else in it is ignored unless the action says otherwise, for any action. `discord.use_replied_message: true` takes the text of the message it replies to, so replying to a message with only the mention files that message. `discord.empty_mention_text` answers any other bare mention with that fixed text, addressing the sender, without running the agent. `discord.forward_user_id: true` hands the sender's Discord user id to the agent's tools as the `discord_user_id` tool context, which a tool's `headers` read as `{{context:discord_user_id}}`. It is the id Discord reported for the message's author, never text the model wrote, so a tool can act for whoever sent it. Off unless set, because tool context reaches every tool the agent has. Read only for `oneshot`. A conversational `agent` in a guild *is* its thread — that is what its session is keyed on — so it always opens one.
  - `id` string, required
  - `project_id` string, required
  - `identifier` string, required
  - `display_name` string, nullable, required
  - `actor_id` string, nullable, required: The actor this address speaks as: the one bound with `actor_id`, else one naturali creates when it first needs it (null until then).
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required

## Other responses

- `201`: Address created with this action.
- `400`: The request was malformed or failed validation.
- `401`: Missing or invalid credentials.
- `403`: The credential is scoped to a different project, or the caller's role in the project does not carry this action.
- `404`: The resource does not exist (existence is not leaked).
- `409`: `actor_minted_for_address`: `actor_id` names the actor naturali created for another address, which erasing that address would delete.

---

[API](https://skmtc.dev/naturali/apis/naturali-ai-api.md) · [All operations](https://skmtc.dev/naturali/apis/naturali-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/naturali/apis/naturali-ai-api/revisions/e4905b78f422?raw)
