# Upgrading to samva 0.37 and the CLI 0.31
URL: https://samva.dev/changelog/upgrade-to-samva-0-37
> samva 0.36 and 0.37 replace send modes with decision rules, delete templates permanently, and drop the RSA verifier. Upgrade the CLI and template toolchain.
- Published: 2026-11-08
- Tags: sdk, cli, api

Upgrade `samva` to 0.37.0, `@samva/webhooks` to 0.37.0, and `@samva/cli` to 0.31.0. Start with decision
rules: send modes, per-grant approval flags, and mailbox policies are gone, and a policy write now
names the version it replaces. Then move template deletion calls and commands, pass the review round
when you approve or deny a held action, upgrade a template project's own authoring packages, and
check for an import of the webhook protocol entrypoint.
Each package's full notes are on its
[GitHub release](https://github.com/SamvaHQ/samva-typescript/releases).

**What you need to do**

1. **Decision rules replace send modes (0.36, CLI 0.31).** A mailbox action now records a decision:
`allow`, `hold`, or `refuse`, with its decider, reason, and the scopes that produced it. Rules live
on one scope, read and written at `GET`, `PUT`, and `DELETE /v1/policies/{kind}/{id}`, where `kind` is
`organization`, `mailbox`, `apiKey`, or `agent`. Each rule sets either a `decide` default or an
`atLeast` floor; a narrower scope replaces a broader default, and every matching floor still
applies. A read returns `version`, and every replacement or clear must pass the observed
`ifVersion`. A stale one returns `ConflictError` (409), so reload the snapshot, review it, and write
again instead of retrying an old configuration. Clearing a scope advances the version too, so an
earlier replacement cannot restore rules you removed. Policy changes need a signed-in person or an
OAuth session; an API key cannot write them. Removed with the old model: mailbox grant and API key
`sendMode`, the mailbox policy operations under `/v1/mailboxes/{id}/policies`, and `sendMode` on an
extension installation, which is now `policy`. See
[configure decision rules](/docs/mailboxes/approvals#configure-decision-rules).

```ts title="set-decision-rules.ts"
import { createClient } from "samva";

const samva = createClient({
  authToken: process.env.SAMVA_OAUTH_TOKEN!,
  orgSlug: process.env.SAMVA_ORG_SLUG!,
});

const current = await samva.policies.getPolicy({ kind: "mailbox", id: "mbx_..." });

await samva.policies.setPolicy({
  kind: "mailbox",
  id: "mbx_...",
  ifVersion: current.version,
  presets: [],
  rules: [{ match: { effect: "write" }, atLeast: "person" }],
});
```

The CLI adds `samva policies get`, `samva policies set`, and `samva policies clear`, each taking a
scope kind and id. Pass `--if-version` with a version you already read; without it, the command reads
the current version first and writes that.

2. **Approvals need the review round (0.36, CLI 0.31).** An approval or denial must carry
`decision.reviewRound` from the action you reviewed. Read the action first and pass that number: a
stale round returns `ConflictError` (409), because the action changed since you read it. Approval
also takes `edits.text` or `edits.html` to send reviewed copy, and `always: true` to allow matching
future actions from the same actor while policy floors and guards still apply. Naming only one email
body clears the other. The CLI requires `--review-round` on `samva mailboxes actions approve` and
`deny`, adds `--edit-text` to approval, and no longer accepts `--send-mode` on `samva api-keys create`
or `samva api-keys update`. Needs you returns `heldAction` items, tool calls included, and counts
them as `heldActions` where it reported `heldSends`; each item carries its `decision`, and a held
tool call also carries its `tool`. Pending-approval webhook events carry the same decision.

```ts title="approve-a-held-action.ts"
import { createClient } from "samva";

const samva = createClient({
  authToken: process.env.SAMVA_OAUTH_TOKEN!,
  orgSlug: process.env.SAMVA_ORG_SLUG!,
});
const mailboxId = "mbx_7q2xk9mvt4znw8rh";
const actionId = "mbxact_7q2xk9mvt4znw8rh";

const action = await samva.mailboxes.getAction({ id: mailboxId, actionId });
if (action.decision === null) throw new Error("This action has no decision to review");

await samva.mailboxes.approveAction({
  id: mailboxId,
  actionId,
  reviewRound: action.decision.reviewRound,
});
```

3. **Template deletion is permanent (0.36, CLI 0.31).** `templates.delete` replaces `templates.remove`
and removes a template with its publications, and `templates.deleteProject` removes a project with
every template in it. Both keep sent-message history and its snapshots, and both refuse a template
that something still uses with `TemplateInUseError` (409) naming each reference by `kind` and `id`.
`isActive` is gone from template responses and from create and update payloads, so a template either
exists or it does not. The CLI renames `samva templates remove` to `samva templates delete <id>`,
previews with `--dry-run`, and confirms with `--yes`; `samva templates projects delete <id>` removes a
project and every template in it. See [delete a template](/docs/api-reference/templates/delete).

4. **Namespace keys reach scheduled sends and reports (0.36, CLI 0.31).** A namespace key can schedule
a message, read analytics, and read conversations in its own namespace, and a scheduled send keeps
that namespace when it fires. With an organization credential, pass `namespaceId` to select one;
scheduled messages and conversations return theirs. A namespace key also reads the organization's
brands. On the CLI, `--namespace` replaces `--namespace-id` on topics and newsletters commands, and
the scheduled-message, analytics, conversation, mailbox, webhook endpoint, and API key commands take
`--namespace`. See [namespaces](/docs/developers/namespaces).

5. **A template project upgrades its authoring packages (CLI 0.31).** `samva templates dev`,
`check`, `render`, `snapshot`, `build`, and `export` load `@samva/markup` and `@samva/vite` from the
project rather than from the CLI, and 0.31 drives the 0.23 release line. A project still on 0.22.x
stops with the version it found and the command that fixes it, so upgrade both packages in the
project:

```bash
npm install --save-dev @samva/markup@~0.23.0 @samva/vite@~0.23.0
```

See [author templates locally](/docs/developers/cli#author-templates-locally).

6. **Webhook verification is HMAC only (0.37).** `@samva/webhooks` 0.37.0 removes
`verifyWebhookAtWithPublicKeys`, `WebhookSignatureVersion`, `webhookSignedContent`, and
`encodeWebhookSignature` from the `@samva/webhooks/protocol` entrypoint. Samva signs deliveries with
HMAC `v1` and never sent the RSA `v2` scheme those exports verified, so a handler that used them has
nothing to check. Verify with `verify` or `verifyRequest` and your endpoint's signing secret; replay
checks, payload decoding, and the Promise and Effect adapters are unchanged. See
[verify each request](/docs/platform/webhooks#2-verify-each-request).

```ts title="verify-with-the-endpoint-secret.ts"
import { verifyRequest } from "@samva/webhooks";

export async function handle(request: Request): Promise<{ id: string; type: string }> {
  const { id, event } = await verifyRequest(request, process.env.SAMVA_WEBHOOK_SECRET!);
  return { id, type: event.type };
}
```

<Staged flag="agents">

**Agents.** An agent definition no longer takes `mode`, and an integration grant no longer takes
`requireApproval`. Both are part of `definition.policy`, the same `presets`, `rules`, and
`instructions` a policy scope holds, and the published policy decides every proposed action. A
`model` rule has Samva judge the action and holds it for a person when judging is unavailable. A
reply is a `write` action, so `mode: "supervised"` becomes a `write` rule at `person`; a `final` rule
alone leaves replies to the `model` default and they can send without a person. Knowledge sources
must belong to the agent's namespace: attach organization-level sources only to an
organization-level agent, or the draft is refused with `ValidationError` (422) and
`definition.knowledgeSourceIds` naming each source. An agent can call `hand_to_team` to hand a
conversation to staff with a held `handoff` decision. Approving with `always` writes an `agent` policy
scope that you can read and clear, and a saved test now expects the decisions for its actions in
`expectedDecisions` instead of `approvedReply`. See
[what needs you](/docs/agents#decide-what-needs-you).

```ts sdk-typecheck-skip="Historical release excerpt; agent definitions no longer take mode"
// Before: the whole definition carried its supervision mode.
await samva.agents.replaceDraft({ id: agentId, revision, definition: { ...definition, mode: "supervised" } });

// After: the same definition carries its decision rules. A reply is a write action, and a final
// rule alone would leave replies to the model default.
await samva.agents.replaceDraft({
  id: agentId,
  revision,
  definition: {
    ...definition,
    policy: {
      presets: [],
      rules: [
        { match: { effect: "write" }, atLeast: "person" },
        { match: { effect: "final" }, atLeast: "person" },
      ],
    },
  },
});
```

</Staged>

**Also new**

- **Search conversations by meaning (0.36).** `mailboxes.listThreads` and
`listOrganizationThreads` take `q` and rank the best 100 matches across subjects, participants,
message text, and attachment filenames. Filters narrow that set without changing its order, and new
mail takes a few seconds to become searchable. See
[search conversations](/docs/mailboxes/read-and-organize#search-conversations).
- **Per-namespace sending health (0.36).** Each namespace sends through its own email sending setup,
so a pause in one namespace leaves the others sending. `email.sending.paused` and
`email.sending.resumed` carry `namespaceId`, or `null` for organization-level sending. See
[email sending events](/docs/platform/webhook-events#email-sending-events).
- **Mailbox sending readiness (0.36).** An email endpoint reports `sendingStatus` as `pending`,
`ready`, or `failed`. Creation returns while the address is still being set up, so pass an
Idempotency-Key to retry safely, including with `samva mailboxes create --idempotency-key`. See
[sending readiness](/docs/mailboxes/manage-mailbox#sending-readiness).
- **A complete sign-in link (CLI 0.31).** `samva login` prints the link that carries the code and asks
you to confirm the page shows the same code. A dropped connection or a temporary server error while
waiting for approval keeps waiting until the code expires.
- **Template editor keys (CLI 0.31).** In `samva templates dev`, <kbd>⌘S</kbd> or <kbd>Ctrl+S</kbd>
saves a version, <kbd>⌘</kbd> or <kbd>Ctrl</kbd> with <kbd>+</kbd>, <kbd>-</kbd>, or <kbd>0</kbd>
zooms the canvas, and <kbd>Escape</kbd> closes an open panel. Keys match the physical key, and on
macOS only <kbd>⌘</kbd> saves or zooms.

## Links

- [TypeScript SDK](/docs/developers/typescript-sdk)
- [Configure decision rules](/docs/mailboxes/approvals#configure-decision-rules)
- [Set decision rules](/docs/api-reference/policies/setPolicy)
- [Delete a template](/docs/api-reference/templates/delete)
- [Verify webhooks](/docs/platform/webhooks#2-verify-each-request)
- [samva 0.37.0 release notes](https://github.com/SamvaHQ/samva-typescript/releases/tag/samva%400.37.0)
- [@samva/webhooks 0.37.0 release notes](https://github.com/SamvaHQ/samva-typescript/releases/tag/%40samva/webhooks%400.37.0)
- [@samva/cli 0.31.0 downloads](https://github.com/SamvaHQ/samva-cli/releases/tag/v0.31.0)

## Related

- [Delete templates and template projects](/changelog/delete-templates-and-template-projects)
- [All changelog entries](/changelog)
