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

# GET /substrate/v1/schema/{pid} — read action schema

> Fetch the ActionSchema map for a process — typed signatures, reversibility class, and parameter lists — without reading the full state objects tree.

The `/schema` endpoint returns every action available on a tracked process, along with each action's type signature, parameter list, reversibility class, and semantic confidence score. Unlike `GET /state`, this endpoint does not return the `objects` map — it is a lightweight call designed for agent planning phases where you need to know what actions exist and how to call them, without the overhead of a full state capture.

## Endpoint

```http theme={null}
GET /substrate/v1/schema/{pid}
X-Substrate-Key: <key>
```

**Rate limit:** 100 requests per second.

## Parameters

<ParamField path="pid" type="integer" required>
  The OS process ID of the target application. Obtain this from `GET /apps`.
</ParamField>

## Response Fields

<ResponseField name="pid" type="integer" required>
  The OS process ID that was queried.
</ResponseField>

<ResponseField name="app_id" type="string" required>
  Stable semantic identifier for the application.
</ResponseField>

<ResponseField name="app_name" type="string" required>
  Human-readable application name.
</ResponseField>

<ResponseField name="schema_version" type="string" required>
  Current semantic schema version in semver format, e.g. `"1.4.2"`. Increments on every accepted `POST /learn` correction.
</ResponseField>

<ResponseField name="actions" type="object" required>
  A map of action names to `ActionSchema` objects. Each key is an action name you can pass to `POST /action`.

  <Expandable title="ActionSchema fields">
    <ResponseField name="signature" type="string">
      Full typed signature in the format `fn(param: type, ...) -> return_type`, e.g. `"fn(thread_id: string, body: string, cc?: string[]) -> bool"`. Parameters marked with `?` are optional.
    </ResponseField>

    <ResponseField name="reversibility" type="string">
      Safety classification for this action. One of:

      | Value                | Meaning                                                        |
      | -------------------- | -------------------------------------------------------------- |
      | `reversible_read`    | Read-only; produces no side effects                            |
      | `reversible_write`   | Write with a known undo path (e.g., archive → unarchive)       |
      | `irreversible_write` | Write with no undo path (e.g., send email, delete permanently) |

      When `reversibility` is `"irreversible_write"`, you **must** include a `verify_expression` in the `POST /action` request or the daemon will reject it.
    </ResponseField>

    <ResponseField name="description" type="string">
      Human-readable description of what the action does, generated by the semantic engine from the runtime method's name, annotations, and call context.
    </ResponseField>

    <ResponseField name="confidence" type="float">
      Semantic engine confidence that this action correctly maps to the underlying runtime method, from `0.0` to `1.0`. Values below `0.85` should be treated with caution — consider submitting a correction via `POST /learn/{pid}`.
    </ResponseField>

    <ResponseField name="parameters" type="array">
      Array of parameter descriptor objects.

      <Expandable title="Parameter descriptor fields">
        <ResponseField name="name" type="string">
          Parameter name as it appears in the action signature.
        </ResponseField>

        <ResponseField name="type_name" type="string">
          JSON type name: `"string"`, `"number"`, `"boolean"`, `"array"`, or `"object"`.
        </ResponseField>

        <ResponseField name="required" type="boolean">
          `true` if the parameter must be present in the `parameters` map of `POST /action`.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

## Examples

<CodeGroup>
  ```bash curl theme={null}
  curl -H "X-Substrate-Key: sk_nsp_..." \
       http://127.0.0.1:7842/substrate/v1/schema/12847
  ```

  ```python Python SDK theme={null}
  from nelieo import NspClient

  client = NspClient(api_key="sk_nsp_...", base_url="http://127.0.0.1:7842")
  session = await client.attach("Gmail")

  # Read actions directly from the session — no extra network call.
  for name, schema in session.actions.items():
      required = [p.name for p in schema.parameters if p.required]
      optional = [p.name for p in schema.parameters if not p.required]
      print(f"{name}")
      print(f"  Signature:     {schema.signature}")
      print(f"  Reversibility: {schema.reversibility}")
      print(f"  Confidence:    {schema.confidence:.2f}")
      print(f"  Required:      {required}")
      print(f"  Optional:      {optional}")
  ```
</CodeGroup>

### Example Response

```json theme={null}
{
  "pid": 12847,
  "app_id": "gmail-chrome-12847",
  "app_name": "Gmail",
  "schema_version": "1.4.2",
  "actions": {
    "send_reply": {
      "signature": "fn(thread_id: string, body: string, cc?: string[]) -> bool",
      "reversibility": "irreversible_write",
      "description": "Send a reply to an email thread",
      "confidence": 0.99,
      "parameters": [
        { "name": "thread_id", "type_name": "string", "required": true },
        { "name": "body",      "type_name": "string", "required": true },
        { "name": "cc",        "type_name": "array",  "required": false }
      ]
    },
    "archive": {
      "signature": "fn(email_id: string) -> bool",
      "reversibility": "reversible_write",
      "description": "Move an email to the archive",
      "confidence": 0.99,
      "parameters": [
        { "name": "email_id", "type_name": "string", "required": true }
      ]
    },
    "mark_as_read": {
      "signature": "fn(email_id: string) -> bool",
      "reversibility": "reversible_write",
      "description": "Mark an email as read",
      "confidence": 0.98,
      "parameters": [
        { "name": "email_id", "type_name": "string", "required": true }
      ]
    }
  }
}
```

## Notes

* The `actions` map returned by `/schema` is identical to the `actions` field in `GET /state`. Use `/schema` when you only need the action list and want to avoid the overhead of transferring the full `objects` map.
* The Python SDK caches the schema on the session object. Calling `session.actions` does not make a network request after the first `attach()` or `refresh()`.
* If a new action appears (e.g., after navigating to a new view), call `GET /state` with `fresh=true` or `GET /schema` again — the session cache is invalidated automatically when `schema_version` changes.
