---
title: "Write complete sequences for up to ten contacts"
method: POST
path: "/sequences/{sequence_id}/agent/training/"
tags: ["sequences"]
---

# Write complete sequences for up to ten contacts

`POST /sequences/{sequence_id}/agent/training/`

## Request

- Base URL: `https://api.getoneprofile.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.getoneprofile.ai/sequences/{sequence_id}/agent/training/`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Writes every message of the sequence for each contact, free, as the AI writing tab shows them. The contacts join the sequence's open writing check, so the ones already written stay and can be read again without writing; a contact already in it is written again, and its Looks good no longer pins its old words. A writing check holds ten contacts: past that, the oldest nobody rated makes room.

## Path parameters

- `sequence_id` string, uuid, required

## Request body

- SequenceTrainingStartSchema
  - `close_open` boolean: Close the sequence's open training session first, keeping its reviews, and start a new one. Without it the contacts join the open session, so the ones already written stay; a contact already in it is written again. Still refused while that session is writing.
  - `record_ids` string[], required

## Response `202`

Successful Response

- SequenceTrainingReadSchema
  - `agent_id` string, uuid, required
  - `applied_version` integer, nullable, required
  - `base_version` integer, required
  - `contacts` SequenceTrainingContactReadSchema[], required
    - `context` object, required
    - `fields` SequenceTrainingContactFieldSchema[], required: The contact's own columns as the run froze them, read the way the approval queue lists a contact: each fact once, a whole-record column opened into its facts.
      - `name` string, required
      - `value` string, required
    - `label` string, required
    - `messages` SequenceTrainingMessageReadSchema[], required
      - `authored` boolean, required
      - `body` string, nullable, required
      - `conditional` string, nullable, required
      - `edited_body` string, nullable, required
      - `edited_subject` string, nullable, required
      - `error` string, nullable, required
      - `facts_used` string[], required
      - `id` string, uuid, required
      - `kind` string, required
      - `looks_good` boolean: These very words are marked Looks good, so they are what sends: by the thread's Looks good, or on their own from the Builder, which marks one email at a time.
      - `note` string, required
      - `previous_body` string, nullable, required
      - `previous_subject` string, nullable, required
      - `proposed_body` string, nullable: The words the rewrite waiting on this contact wrote.
      - `proposed_error` string, nullable: Why the rewrite could not write this message.
      - `proposed_send` SequenceTrainingSendSchema: Whether a message would leave on its own when its turn comes, and if not, why.
        - `alone` boolean, required: True when the send would let these words go without a person; false when they would wait for approval in Tasks.
        - `doubt` string, nullable: When the words themselves hold the message (the agent was not confident, knew too little, or a check found something): one sentence saying what. Null otherwise.
        - `reason` 'low_confidence' | 'findings' | 'insufficient_data' | 'policy' | 'always_ask' | 'sequence_manual' | 'step_requires_approval' | 'daily_cap' | 'unverified_sender' | 'suppressed' | 'different_sender' | 'label' | 'question' | 'consecutive_cap' | 'thread_cap' | 'hourly_cap' | 'org_daily_cap' | 'stale_inbound' | 'sequence_gone' | 'bot_question' | 'automated_counterparty' | 'kill_switch' | 'authentication' | 'language' | 'linkedin_only' | 'send_interrupted' | 'sender_switched_to_manual', required: Why a message that could have sent unattended was put in front of a person. One vocabulary for every gate between an agent writing a message and the message leaving: what the agent itself said about the draft (``LOW_CONFIDENCE``, ``FINDINGS``, ``INSUFFICIENT_DATA``, ``POLICY``), what the sender or the cadence asked for (``ALWAYS_ASK``, ``SEQUENCE_MANUAL``, ``STEP_REQUIRES_APPROVAL``), what the pacing rules refused (``DAILY_CAP``, ``CONSECUTIVE_CAP``, ``THREAD_CAP``, ``HOURLY_CAP``, ``ORG_DAILY_CAP``), what the mailbox or the thread made unsafe (``UNVERIFIED_SENDER``, ``DIFFERENT_SENDER``, ``LABEL``, ``QUESTION``, ``STALE_INBOUND``, ``SEQUENCE_GONE``), and what the counterparty turned out to be (``BOT_QUESTION``, ``AUTOMATED_COUNTERPARTY``, ``AUTHENTICATION``, ``LANGUAGE``, ``LINKEDIN_ONLY``). ``KILL_SWITCH`` is the platform switch that stops unattended sending outright, and ``SEND_INTERRUPTED`` an unattended reply whose send never got as far as a provider. ``SENDER_SWITCHED_TO_MANUAL`` is a LinkedIn step queued unasked that went back to a person because its sender switched to manual before it ran. Stored on the task so the queue can say why each row is there, and so "why did nothing send" is answerable by counting rows rather than by reading logs.
      - `proposed_subject` string, nullable: The subject the message sends with once the rewrite waiting on this contact is kept: the rewrite's own, or the subject typed on the step, which a rewrite keeps.
      - `reasoning` string, nullable, required
      - `reply_to_step_id` string, uuid, nullable, required: The step whose thread this message replies in, or null when it opens a thread of its own.
      - `send` SequenceTrainingSendSchema: Whether a message would leave on its own when its turn comes, and if not, why.
        - `alone` boolean, required: True when the send would let these words go without a person; false when they would wait for approval in Tasks.
        - `doubt` string, nullable: When the words themselves hold the message (the agent was not confident, knew too little, or a check found something): one sentence saying what. Null otherwise.
        - `reason` 'low_confidence' | 'findings' | 'insufficient_data' | 'policy' | 'always_ask' | 'sequence_manual' | 'step_requires_approval' | 'daily_cap' | 'unverified_sender' | 'suppressed' | 'different_sender' | 'label' | 'question' | 'consecutive_cap' | 'thread_cap' | 'hourly_cap' | 'org_daily_cap' | 'stale_inbound' | 'sequence_gone' | 'bot_question' | 'automated_counterparty' | 'kill_switch' | 'authentication' | 'language' | 'linkedin_only' | 'send_interrupted' | 'sender_switched_to_manual', required: Why a message that could have sent unattended was put in front of a person. One vocabulary for every gate between an agent writing a message and the message leaving: what the agent itself said about the draft (``LOW_CONFIDENCE``, ``FINDINGS``, ``INSUFFICIENT_DATA``, ``POLICY``), what the sender or the cadence asked for (``ALWAYS_ASK``, ``SEQUENCE_MANUAL``, ``STEP_REQUIRES_APPROVAL``), what the pacing rules refused (``DAILY_CAP``, ``CONSECUTIVE_CAP``, ``THREAD_CAP``, ``HOURLY_CAP``, ``ORG_DAILY_CAP``), what the mailbox or the thread made unsafe (``UNVERIFIED_SENDER``, ``DIFFERENT_SENDER``, ``LABEL``, ``QUESTION``, ``STALE_INBOUND``, ``SEQUENCE_GONE``), and what the counterparty turned out to be (``BOT_QUESTION``, ``AUTOMATED_COUNTERPARTY``, ``AUTHENTICATION``, ``LANGUAGE``, ``LINKEDIN_ONLY``). ``KILL_SWITCH`` is the platform switch that stops unattended sending outright, and ``SEND_INTERRUPTED`` an unattended reply whose send never got as far as a provider. ``SENDER_SWITCHED_TO_MANUAL`` is a LinkedIn step queued unasked that went back to a person because its sender switched to manual before it ran. Stored on the task so the queue can say why each row is there, and so "why did nothing send" is answerable by counting rows rather than by reading logs.
      - `steps` AiStep[], required
        - `action` string, required: What kind of move this was, e.g. `read_table`, `plan`, `write_column`.
        - `detail` string: The step's input: the instruction, the column it read, the query it ran.
        - `duration_ms` integer, nullable: Wall clock for the work this step describes, never an estimate.
        - `observation` string: One line on what came back. The half that makes a step worth reading.
        - `outcome` string: `completed`, `failed`, `refused` or `stopped`. Clients must tolerate new tokens.
        - `thought` string, nullable: The model's stated reasoning for choosing this step. Set by the agent loop; the assistant surfaces leave it null, and the renderer simply omits the rung.
      - `subject` string, nullable, required
      - `timing` string, required
      - `title` string, required
    - `note` string, required
    - `notes` SequenceTrainingNoteReadSchema[]: Every note given on this thread, oldest first.
      - `note` string, required
      - `state` 'pending' | 'applied' | 'discarded' | 'settled', required: Where one note stands: being answered, learned, thrown away, or answered with no change.
    - `notice` string, nullable: The agent's answer to a note that needed no change to its instructions, in its own sentence: usually a note about this contact's own facts.
    - `profile_mismatch` string, nullable: What the contact's LinkedIn profile says that their row does not, usually a job change the row has not caught up with, as one sentence: 'LinkedIn says Operations Leader at Chamber Media; the row says Sealed.' Null when they agree or no profile was read.
    - `record_id` string, uuid, required
    - `sender_profile_id` string, uuid, nullable: The sender these messages were written as, when the run chose one: where a message held because this sender always asks is changed.
    - `verdict` 'good' | 'bad' | 'skipped', required: Only an explicit review counts as feedback.
  - `created_at` string, date-time, required
  - `error` string, nullable, required
  - `id` string, uuid, required
  - `note_waiting` boolean: A note was given while another contact was being written: its rewrite is worked out as soon as that write lands.
  - `progress` SequenceTrainingProgressSchema, required: How training on this sequence is going, counted across the run.
    - `fixed` integer, required: Lessons kept in this run.
    - `in_a_row` integer, required: Contacts given Looks good, with no note, since the last note.
    - `lessons` string[], required: Each lesson kept, in the agent's own sentence, oldest first.
    - `ready` boolean, required: Whether in_a_row has reached ready_after.
    - `ready_after` integer, required: How many in a row make the agent ready to send on its own.
    - `reviewed` integer, required: Contacts given Looks good or a note in this run.
  - `proposal` ContactTrainingProposal, required: The session's candidate prompt update, kept pending until applied.
    - `changes` ContactPromptChange[]
      - `current` string, required
      - `proposed` string, required
      - `rationale` string, required
      - `slot_key` string, required
    - `made_at` integer
    - `record_id` string, uuid, nullable
    - `round_ids` string[]
    - `summary` string, required
  - `reviewed_ids` string[]: Every contact given Looks good or a note in this run, including ones that left the run to make room.
  - `revision` integer, required
  - `status` 'running' | 'reviewing' | 'proposing' | 'proposed' | 'completed' | 'abandoned', required: A session's phase, also used to resume its review screen.
  - `steps` AiStep[]
    - `action` string, required: What kind of move this was, e.g. `read_table`, `plan`, `write_column`.
    - `detail` string: The step's input: the instruction, the column it read, the query it ran.
    - `duration_ms` integer, nullable: Wall clock for the work this step describes, never an estimate.
    - `observation` string: One line on what came back. The half that makes a step worth reading.
    - `outcome` string: `completed`, `failed`, `refused` or `stopped`. Clients must tolerate new tokens.
    - `thought` string, nullable: The model's stated reasoning for choosing this step. Set by the agent loop; the assistant surfaces leave it null, and the renderer simply omits the rung.

## Other responses

- `401`: Unauthorized
- `403`: Forbidden
- `404`: Sequence, audience contact, or session not found
- `409`: Sequence, agent, or training revision changed
- `422`: Invalid selection, feedback, or training action
- `500`: Internal server error.
- `502`: Bad gateway error.
- `503`: Service unavailable.

---

[API](https://skmtc.dev/getoneprofile/apis/api-reference-oneprofile.md) · [All operations](https://skmtc.dev/getoneprofile/apis/api-reference-oneprofile/llms.txt) · [OpenAPI document](https://skmtc.dev/getoneprofile/apis/api-reference-oneprofile/revisions/4a6bd71e3f02?raw)
