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

# Acquire a numeric action sequence

> Configure episode_credit, request a sequence, execute it, and submit the actual states, actions, validity, and outcome.

This guide continues the two-actuator example in [Schemas and configuration](/docs/machina/configuration). Use its production URL, authentication, and Python helpers. The API fields follow the reference schema and client; the planar adapter is an illustrative application you supply.

## Configure the acquisition stage

```python theme={null}
config = {
    "mechanism": "episode_credit",
    "state_dimensions": 4,
    "action_dimensions": 2,
    "goal_indices": [0, 1],
    "horizon": 8,
    "capacity": 128,
    "max_pending": 1,
    "seed": 1,
    "outcome_mode": "reward",
}
configuration_receipt, initial_state = create_stage(
    ACQUISITION_DOMAIN, config
)
```

Create/configure once for a fresh run, not at every episode. Keep this Domain ID across compatible attempts.

## Request one sequence

POST to `https://rei-neuroadapt-api.reilabs.org/api/v1/domains/{domain_id}/trajectory/propose`:

```json theme={null}
{
  "state": [0.0, 0.0, 0.0, 0.0],
  "goal": [0.5, 0.5],
  "mode": "explore",
  "request_id": "control-example-attempt-0001",
  "seed": 1
}
```

These numeric inputs illustrate the four-state/two-goal schema. In the runner, replace them with the actual reset observation and requested goal.

| Field                   | Contract                                                                                                        |
| ----------------------- | --------------------------------------------------------------------------------------------------------------- |
| `state`                 | Current measured vector of `state_dimensions` finite numbers                                                    |
| `goal`                  | Desired coordinates in `goal_indices` order                                                                     |
| `mode`                  | Explicitly `explore` for acquisition; the schema default is `frozen`                                            |
| `request_id`            | Application request identifier; preserve it through reconciliation, but do not assume it guarantees idempotency |
| `seed`                  | Optional learner proposal seed; keep separate from the environment reset key                                    |
| `acquisition_reference` | Optional authoritative retained record ID when using the context-revisit workflow below                         |

The reference client consumes `decision_id` and `actions` from the response. `actions` is a nonempty matrix with one row per proposed command and `action_dimensions` columns. It also reads `reference_state` and `reference_valid` when applying an explicit geometric retargeting transform. An action proposal is not evidence that the action was executed.

## Implement the application adapter

The following are application functions, not API endpoints:

| Hook                           | Required behavior                                                                                                     |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `reset_and_measure(reset_key)` | Restore the environment; return `state`, `goal`, and Boolean `initial_valid`                                          |
| `execute_sequence(actions)`    | Decode normalized controls, apply the fixed command cadence, and record actual states/actions until termination       |
| `measure_outcome(trace)`       | Return `float(completed)` using the distance, speed, assessment-time, and safety-stop rule in the configuration guide |
| `journal(kind, record)`        | Durably append local intent, execution, and response records without credentials                                      |

For this example, normalize each actuator command to `[-1, 1]`. Keep the physical mapping and 0.5-second hold duration fixed. Pad a proposal shorter than eight commands with neutral `[0.0, 0.0]` commands before execution. These are real applied commands and belong in the returned trace. Preserve the original proposal separately. Store physical commands alongside the native numeric coordinates so the actual applied operation is reconstructable.

## Align the observation arrays

For `T` commands actually executed:

| Field                  | Shape / meaning                                                                                     |
| ---------------------- | --------------------------------------------------------------------------------------------------- |
| `decision_id`          | The returned proposal ID                                                                            |
| `states`               | `(T + 1) × state_dimensions`: initial state followed by each measured successor                     |
| `actions`              | `T × action_dimensions`: actual performed commands in the declared native coordinate representation |
| `outcome`              | Measured scalar terminal/whole-attempt outcome; explicitly supplied in reward mode                  |
| `observation_validity` | Optional `T + 1` Booleans aligned with the state rows                                               |
| `step_outcomes`        | Optional `T` measured per-command outcomes; omit if the adapter only measures the final outcome     |

The `T`/`T+1` alignment is enforced by the runner pattern, not fully expressed by the JSON schema. Check it before sending. For an early physical stop, return only the executed prefix. Never append unexecuted proposal rows to make the array reach the configured horizon.

If no command executed, do not send an empty or fabricated observation. Preserve the pending decision and use supported cancellation when appropriate. Keep invalid measurements separate from a valid physical attempt with a poor outcome.

## Connect the loop

This code depends on the adapter hooks above and the request helper from the configuration guide. It supplies no task-solving controller or simulator.

```python theme={null}
import math

def finite_matrix(rows, width):
    return bool(rows) and all(
        len(row) == width
        and all(
            isinstance(value, (int, float))
            and not isinstance(value, bool)
            and math.isfinite(value)
            and abs(value) <= 1e12
            for value in row
        )
        for row in rows
    )

def acquire_once(attempt, reset_key):
    initial = reset_and_measure(reset_key)
    if type(initial["initial_valid"]) is not bool:
        raise ValueError("Initial validity must be Boolean")
    body = {
        "state": initial["state"],
        "goal": initial["goal"],
        "mode": "explore",
        "request_id": f"{PREFIX}-attempt-{attempt:06d}",
        "seed": attempt,
    }
    journal("propose_intent", body)
    proposal = trajectory(ACQUISITION_DOMAIN, "propose", body)
    journal("proposal", proposal)
    commands = proposal["actions"]
    if not finite_matrix(commands, 2) or len(commands) > 8:
        raise ValueError("Invalid proposed action shape")
    if any(abs(value) > 1 for row in commands for value in row):
        raise ValueError("Direct proposal exceeds this executor's bounds")

    executable_commands = commands + [[0.0, 0.0] for _ in range(8 - len(commands))]
    journal("execution_plan", {"actions": executable_commands})
    trace = execute_sequence(executable_commands)
    journal("execution", trace)  # Persist before feedback can be sent.
    count = len(trace["actions"])
    if not 1 <= count <= len(executable_commands):
        raise ValueError("No valid executed prefix")
    if not finite_matrix(trace["actions"], 2):
        raise ValueError("Invalid executed actions")
    if any(abs(value) > 1 for row in trace["actions"] for value in row):
        raise ValueError("Executed native coordinates exceed declared bounds")
    if not finite_matrix(trace["states"], 4):
        raise ValueError("Invalid measured states")
    if len(trace["states"]) != count + 1:
        raise ValueError("Expected one initial state and one state per command")
    if trace["states"][0] != initial["state"]:
        raise ValueError("Trace must start with the proposal's measured state")

    observation = {
        "decision_id": proposal["decision_id"],
        "states": trace["states"],
        "actions": trace["actions"],
        "outcome": measure_outcome(trace),
    }
    if "observation_validity" in trace:
        validity = trace["observation_validity"]
        if len(validity) != count + 1 or any(type(v) is not bool for v in validity):
            raise ValueError("Validity must align with states")
        if validity[0] != initial["initial_valid"]:
            raise ValueError("Initial validity changed between reset and trace")
        observation["observation_validity"] = validity
    elif not initial["initial_valid"]:
        raise ValueError("An invalid initial measurement requires explicit validity")
    if "step_outcomes" in trace:
        if (len(trace["step_outcomes"]) != count
                or not finite_matrix([trace["step_outcomes"]], count)):
            raise ValueError("Step outcomes must align with actions")
        observation["step_outcomes"] = trace["step_outcomes"]
    if observation["outcome"] not in (0.0, 1.0):
        raise ValueError("This example uses a binary measured completion outcome")

    journal("observe_intent", observation)
    receipt = trajectory(ACQUISITION_DOMAIN, "observe", observation)
    journal("observe_receipt", receipt)
    journal("state_after", trajectory(ACQUISITION_DOMAIN, "state"))
    return receipt
```

The observation route is `POST /domains/{domain_id}/trajectory/observe`, relative to the production base. Do not send this body to generic Domain `/feedback`. Report neutral padding only when it actually executed. A safety stop takes precedence over completing the eight-slot window.

Validate outcome range and direction in `measure_outcome`. `json.dumps(..., allow_nan=False)` in the shared transport rejects non-finite values before dispatch. If safety logic changes an action, retain both proposal and actual execution and the reason; do not claim the original proposal was executed unchanged.

## Revisit an acquired context

The optional context workflow asks the learner for a retained acquisition reference:

```json theme={null}
{
  "target_outcome": 1.0,
  "seed": 2
}
```

Send it to `POST /domains/{domain_id}/trajectory/context`. The client reads `response.request`; when non-null, it uses `request.record_id` to restore the associated environment context and supplies that same ID as `acquisition_reference` in the next proposal.

Maintain an authoritative native-record-ID to local-reset mapping. Record IDs are not guaranteed to equal attempt counters. If the mapping is unavailable, do not invent it. Ordinary reset sampling can continue without this optional context-revisit feature.

## Continue

Stop acquisition at the application-owned budget boundary, reconcile pending work, and export a stable retained source for [selection, deletion, and ordering](/docs/machina/structural-stages). To use the acquired state directly, see [Retained use and recovery](/docs/machina/retained-use).
