---
title: "Edit Learning Statement"
method: PATCH
path: "/api/domains/{domain_id}/agent-desk/learnings/{version_id}"
tags: ["agent_desk"]
---

# Edit Learning Statement

`PATCH /api/domains/{domain_id}/agent-desk/learnings/{version_id}`

## Request

- Base URL: `https://api-v1.unusual.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api-v1.unusual.ai/api/domains/{domain_id}/agent-desk/learnings/{version_id}`
- Auth: OAuth 2
  - Password
  - Token URL: `/auth/login`

"Edit": reword what a memory SAYS, without touching what the AgentDesk answers.

The sentence and the document are different objects, and this endpoint only reaches
the first. A learning's statement is byte-equal to its version's `change_summary`
by contract, so `_set_learning_statement` rewrites both together; an automatic site
update carries no such contract (its `change_summary` is the compiler's, not the
owner's) so only the block moves.

The edit is STAMPED inside the block (`edited_by` / `edited_at`) rather than left
invisible: a ledger whose sentences can be rewritten silently is a ledger a support
thread cannot reason about, and the stamp is the difference between "the AgentDesk
said this" and "somebody rewrote what the AgentDesk said".

THE JSONB TRAP, written down because it has bitten this codebase twice: the column
has no mutation tracking, so a nested in-place edit is a change SQLAlchemy never
flushes. Every write below builds a NEW dict and reassigns the attribute.

Refusals: 400 a malformed id or an empty statement · 404 not this AgentDesk's
memory · 409 the version carries no memory to reword.

## Path parameters

- `version_id` string, required
- `domain_id` string, required

## Headers

- `x-view-as` string, nullable

## Request body

- LearningStatementUpdate: The reworded memory. One field, because one field is all that is editable. No product limit (Will, 2026-10-14: the 240-char cap is gone); the hidden owner-text guardrail is enforced HERE as well as at the write, matching `LearningApprove.statement_override`, so an absurd paste is a 422 the field can show, not a silent truncation the owner discovers on the next reload.
  - `statement` string, required

## Response `200`

Successful Response

- LearningStatementOut
  - `version_id` string, required
  - `kind` string, required
  - `statement` string, required
  - `detail` string, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/unusual/apis/dashboard-server.md) - [All operations](https://skmtc.dev/unusual/apis/dashboard-server/llms.txt) - [OpenAPI document](https://skmtc.dev/unusual/apis/dashboard-server/revisions/89f716930ead?raw)
