# Points de contrôle

A **point de contrôle** demande l'approbation d'une action d'un seul agent. Vous en créez une avant que l'action ne s'exécute ; Maetra l'évalue contre votre actif [politiques](https://maetra.io/fr/docs/govern-api/policies) et retourne une décision - immédiatement pour des résultats rapides, ou après une réponse humaine.

### Cycle de vie

```
create ─▶ evaluate ─┬─▶ approved / rejected / blocked   (terminal, signed)
                    └─▶ pending ─▶ (human decides) ─▶ approved / rejected
                                └─▶ (timeout)      ─▶ expired
```

| État | Signification |
| ----------- | ------------------------------------------------ |
| `pending` | En attente d'une décision humaine. Sondage pour le résultat. |
| `approved` | Autorisé. A `decision_token` est émis. |
| `rejected` | Un examinateur a refusé. |
| `blocked` | Une politique l'a bloquée automatiquement (pas besoin d'être humain). |
| `expired` | Aucune décision avant l'expiration du délai. |
| `cancelled` | Annulé avant résolution. |

Seulement `approved` les décisions peuvent continuer à faire l'objet d'une autorisation d'exécution à usage unique.

### Créer un point de contrôle

`POST /v1/checkpoints` — demande une portée `govern:checkpoints:write`.

Évaluation synchrone : une politique de voie rapide peut renvoyer une décision finale dans la même réponse; sinon vous obtenez une `pending` checkpoint pour le scrutin.

#### Politiques exactes et renseignement décisionnel

`/v1/checkpoints` utilise les politiques actives configurées dans Govern. Une politique peut utiliser des conditions exactement sauvegardées, ou elle peut utiliser **Renseignements sur la décision de l'agent de l'IA** évaluer le risque d'exécution.

C'est vrai. **pas** envoyer un `decision_intelligence` drapeau sur la demande de contrôle. Permettre l'information décisionnelle sur la politique dans le tableau de bord. L'appel API reste le même ; Maetra applique le mode politique et retourne la même forme de décision de point de contrôle.

**Organisme de demande**

| Champ | Type | Requis | Désignation des marchandises |
| ------------------ | --------- | -------- | ------------------------------------------------------------ |
| `action` | chaîne de caractères | ✓ | Le nom de l'action, p. ex. `transfer_funds`. |
| `payload` | objet || Détails structurés de l'action. |
| `agent_name` | chaîne de caractères || Appelable à lecture humaine (utiliser lorsque l'agent n'est pas enregistré). |
| `agent_id` | chaîne de caractères || Numéro d'identification de l'agent enregistré (voir [Agents](https://maetra.io/fr/docs/agents)). |
| `context` | chaîne de caractères || Contexte en texte libre pour les évaluateurs. |
| `reasoning` | chaîne de caractères || Le raisonnement de l'agent. |
| `autonomy_level` | chaîne de caractères || Niveau d'autonomie des agents, `L0`–`L5`. |
| `policy_ids` | chaîne de caractères\[] || Restreindre l'évaluation à ces politiques d'intelligence exacte ou décisionnelle. |
| `policy_group_ids` | chaîne de caractères\[] || Restreindre l'évaluation à ces groupes stratégiques. |
| `timeout_seconds` | entier || Plafond horaire pour une décision humaine. |
| `target` | objet || Compte, ressource ou fournisseur que l'action aura une incidence. |
| `task_authorization` | objet || Identification des tâches, des révisions et des actions extérieures qui ont autorisé les travaux. |
| `runtime` | objet || Noms d'outils et de modèles et versions utilisés pour proposer l'action. |
| `executor_audience` | chaîne de caractères || Service autorisé à consommer la capacité approuvée. |

#### cURL

```bash
curl -X POST "https://api.maetra.io/v1/checkpoints" \
  -H "Authorization: Bearer $MAETRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "action": "delete_customer",
  "agent_name": "ops-agent",
  "payload": {
    "customer_id": "cus_41ab"
  },
  "reasoning": "GDPR erasure request #8821."
}'
```

#### JavaScript

```javascript
const res = await fetch("https://api.maetra.io/v1/checkpoints", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.MAETRA_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
      "action": "delete_customer",
      "agent_name": "ops-agent",
      "payload": {
          "customer_id": "cus_41ab"
      },
      "reasoning": "GDPR erasure request #8821."
  }),
});
if (!res.ok) throw new Error(`Maetra API ${res.status}`);
const data = await res.json();
console.log(data);
```

#### TypeScript

```typescript
interface CheckpointDecision {
  checkpoint_id: string;
  status: string;
  decision_token: string | null;
  expires_at: string | null;
  evals: unknown[];
}

const res = await fetch("https://api.maetra.io/v1/checkpoints", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.MAETRA_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
      "action": "delete_customer",
      "agent_name": "ops-agent",
      "payload": {
          "customer_id": "cus_41ab"
      },
      "reasoning": "GDPR erasure request #8821."
  }),
});
if (!res.ok) throw new Error(`Maetra API ${res.status}`);
const data = (await res.json()) as CheckpointDecision;
```

#### Python

```python
import os, requests

res = requests.post(
    "https://api.maetra.io/v1/checkpoints",
    headers={"Authorization": f"Bearer {os.environ['MAETRA_API_KEY']}"},
    json={
        "action": "delete_customer",
        "agent_name": "ops-agent",
        "payload": {
            "customer_id": "cus_41ab"
        },
        "reasoning": "GDPR erasure request #8821."
    },
)
res.raise_for_status()
print(res.json())
```

#### Rust

```rust
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let key = std::env::var("MAETRA_API_KEY")?;
    let client = reqwest::Client::new();
    let res = client
        .post("https://api.maetra.io/v1/checkpoints")
        .bearer_auth(&key)
        .json(&json!({
            "action": "delete_customer",
            "agent_name": "ops-agent",
            "payload": {
                "customer_id": "cus_41ab"
            },
            "reasoning": "GDPR erasure request #8821."
        }))
        .send()
        .await?;
    let data: serde_json::Value = res.json().await?;
    println!("{data:#}");
    Ok(())
}
```

#### C++

```cpp
#include <curl/curl.h>
#include <cstdlib>
#include <string>

int main() {
    CURL* curl = curl_easy_init();
    std::string auth = "Authorization: Bearer " + std::string(std::getenv("MAETRA_API_KEY"));
    struct curl_slist* headers = nullptr;
    headers = curl_slist_append(headers, auth.c_str());
    headers = curl_slist_append(headers, "Content-Type: application/json");
    curl_easy_setopt(curl, CURLOPT_URL, "https://api.maetra.io/v1/checkpoints");
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, R"({  "action": "delete_customer",  "agent_name": "ops-agent",  "payload": {    "customer_id": "cus_41ab"  },  "reasoning": "GDPR erasure request #8821."})");
    curl_easy_perform(curl);   // response is written to stdout by default
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    return 0;
}
```

#### Java

```java
import java.net.URI;
import java.net.http.*;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.maetra.io/v1/checkpoints"))
    .header("Authorization", "Bearer " + System.getenv("MAETRA_API_KEY"))
    .header("Content-Type", "application/json")
    .method("POST", HttpRequest.BodyPublishers.ofString("""
{
  "action": "delete_customer",
  "agent_name": "ops-agent",
  "payload": {
    "customer_id": "cus_41ab"
  },
  "reasoning": "GDPR erasure request #8821."
}"""))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```


#### Avec un agent enregistré

L'appel ci-dessus utilise `agent_name` parce que l'agent n'est pas enregistré — le cas commun. Si l'agent **est** [enregistrés](https://maetra.io/fr/docs/agents), passez son `agent_id` à la place (ou à côté `agent_name`) donc le point de contrôle lui est attribué :

```json
{
  "action": "delete_customer",
  "agent_id": "agt_5Ab2",
  "payload": { "customer_id": "cus_41ab" },
  "reasoning": "GDPR erasure request #8821."
}
```

#### Portée de la politique avec identité d'agent optionnelle

`agent_id` est facultatif pour `/v1/checkpoints`C'est vrai. Lorsque vous n'envoyez que `agent_name`Govern évalue toujours l'action.

Pour l'évaluation automatique des politiques actives:

| Demande d'identité | Politiques envisagées |
| ------------------------------------ | --------------------------------------------------------------------------------------------- |
| Enregistré `agent_id` | Politiques à l'échelle de l'organisation, plus les politiques attribuées à cet agent enregistré. |
| `agent_name` correspondant à un agent enregistré | Politiques à l'échelle de l'organisation, plus les politiques attribuées à cet agent enregistré. |
| Inconnu ou non enregistré `agent_name` | Politiques à l ' échelle de l ' Organisation seulement. Les politiques spécifiques à l'agent ne s'exécutent pas accidentellement. |
| Pas d'identité d'agent | Politiques à l ' échelle de l ' Organisation seulement. |

Utilisation `agent_id` pour une attribution stable. Utilisation `agent_name` pour les agents API ou MCP qui n'ont pas encore été enregistrés. Si vous passez `policy_ids` ou `policy_group_ids`, Maetra évalue cette sélection explicite. La sélection peut inclure des politiques précises ou des politiques d'intelligence décisionnelle.

#### Réponse

```json
{
  "checkpoint_id": "cp_7Yh2Qa",
  "agent_id": null,
  "agent_name": "ops-agent",
  "status": "pending",
  "reason": null,
  "decision_token": null,
  "expires_at": "2026-07-07T12:05:00.000Z",
  "evals": [
    { "policy_name": "Destructive actions", "status": "pending", "quorum_required": 2, "quorum_met": 0, "pool_size": 4 }
  ]
}
```

| Champ | Type | Désignation des marchandises |
| ------------------------- | -------------- | ----------------------------------------------------------------------------------------------- |
| `checkpoint_id` | chaîne de caractères | La carte d'identité du poste de contrôle. |
| `agent_id` / `agent_name` | chaîne de caractères \| null | L'identité de l'appelant que vous avez fournie. |
| `status` | enum | `pending`, `approved`, `rejected`, `expired`, `blocked`, `cancelled`. |
| `reason` | chaîne de caractères \| null | Raison humaine ou politique, quand elle est disponible. |
| `decision_token` | chaîne de caractères \| null | JWT Signé prouvant une décision finale — voir [Jetons de décision](https://maetra.io/fr/docs/govern-api/decision-tokens). |
| `action_envelope` / `action_envelope_hash` | objet / chaîne | Proposition exacte et reliure canonique SHA-256. |
| `policy_versions` / `policy_digest` | tableau / chaîne | Les versions exactes de la politique utilisées pour la décision. |
| `decision_token_expires_at` | chaîne de caractères \| null | Expiration de la capacité de décision signée à usage unique. |
| `execution_expected_at` / `effect_expected_at` | chaîne de caractères \| null | Les dates limites utilisées pour faire ressortir les preuves manquantes du cycle de vie. |
| `expires_at` | chaîne de caractères \| null | péremption ISO 8601. |
| `evals` | tableau | Détail de l'évaluation par politique (ci-dessous). |

**Objet Eval:** `policy_id`, `policy_name`, `applicability`, `status`, `quorum_required`, `quorum_met`, `pool_size`.

### Obtenez un point de contrôle (sondage froid)

`GET /v1/checkpoints/{id}` — champ d'application `govern:checkpoints:read`C'est vrai. Retourne l'état actuel sans attendre. Garder ≥ 1 seconde entre les sondages du même point de contrôle; préférer le long-poll ci-dessous.

#### cURL

```bash
curl "https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa" \
  -H "Authorization: Bearer $MAETRA_API_KEY"
```

#### JavaScript

```javascript
const res = await fetch("https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.MAETRA_API_KEY}`,
  },
});
if (!res.ok) throw new Error(`Maetra API ${res.status}`);
const data = await res.json();
console.log(data);
```

#### TypeScript

```typescript
const res = await fetch("https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.MAETRA_API_KEY}`,
  },
});
if (!res.ok) throw new Error(`Maetra API ${res.status}`);
const data = (await res.json());
```

#### Python

```python
import os, requests

res = requests.get(
    "https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa",
    headers={"Authorization": f"Bearer {os.environ['MAETRA_API_KEY']}"},
)
res.raise_for_status()
print(res.json())
```

#### Rust

```rust
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let key = std::env::var("MAETRA_API_KEY")?;
    let client = reqwest::Client::new();
    let res = client
        .get("https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa")
        .bearer_auth(&key)
        .send()
        .await?;
    let data: serde_json::Value = res.json().await?;
    println!("{data:#}");
    Ok(())
}
```

#### C++

```cpp
#include <curl/curl.h>
#include <cstdlib>
#include <string>

int main() {
    CURL* curl = curl_easy_init();
    std::string auth = "Authorization: Bearer " + std::string(std::getenv("MAETRA_API_KEY"));
    struct curl_slist* headers = nullptr;
    headers = curl_slist_append(headers, auth.c_str());
    curl_easy_setopt(curl, CURLOPT_URL, "https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_perform(curl);   // response is written to stdout by default
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    return 0;
}
```

#### Java

```java
import java.net.URI;
import java.net.http.*;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa"))
    .header("Authorization", "Bearer " + System.getenv("MAETRA_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```


### Attendez une décision (long-poll)

`GET /v1/checkpoints/{id}/wait` — champ d'application `govern:checkpoints:read`C'est vrai. Maintient la connexion ouverte jusqu'à ce que le point de contrôle change d'état ou que la cale s'écoule. La façon efficace d'attendre un humain.

* Demande `timeout`: tenir les secondes, `1`–`55` (par défaut) `50`).
* `200` — changé; le corps est le nouvel état. `202` — pas de changement; reconnecter.

#### cURL

```bash
curl "https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa/wait?timeout=50" \
  -H "Authorization: Bearer $MAETRA_API_KEY"
```

#### JavaScript

```javascript
const res = await fetch("https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa/wait?timeout=50", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.MAETRA_API_KEY}`,
  },
});
if (!res.ok) throw new Error(`Maetra API ${res.status}`);
const data = await res.json();
console.log(data);
```

#### TypeScript

```typescript
const res = await fetch("https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa/wait?timeout=50", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.MAETRA_API_KEY}`,
  },
});
if (!res.ok) throw new Error(`Maetra API ${res.status}`);
const data = (await res.json());
```

#### Python

```python
import os, requests

res = requests.get(
    "https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa/wait?timeout=50",
    headers={"Authorization": f"Bearer {os.environ['MAETRA_API_KEY']}"},
)
res.raise_for_status()
print(res.json())
```

#### Rust

```rust
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let key = std::env::var("MAETRA_API_KEY")?;
    let client = reqwest::Client::new();
    let res = client
        .get("https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa/wait?timeout=50")
        .bearer_auth(&key)
        .send()
        .await?;
    let data: serde_json::Value = res.json().await?;
    println!("{data:#}");
    Ok(())
}
```

#### C++

```cpp
#include <curl/curl.h>
#include <cstdlib>
#include <string>

int main() {
    CURL* curl = curl_easy_init();
    std::string auth = "Authorization: Bearer " + std::string(std::getenv("MAETRA_API_KEY"));
    struct curl_slist* headers = nullptr;
    headers = curl_slist_append(headers, auth.c_str());
    curl_easy_setopt(curl, CURLOPT_URL, "https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa/wait?timeout=50");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_perform(curl);   // response is written to stdout by default
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    return 0;
}
```

#### Java

```java
import java.net.URI;
import java.net.http.*;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.maetra.io/v1/checkpoints/cp_7Yh2Qa/wait?timeout=50"))
    .header("Authorization", "Bearer " + System.getenv("MAETRA_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```


### Débit recommandé

1. `POST /v1/checkpoints`.
2. Si `status` est déjà terminal, agir dessus (et vérifier le jeton).
3. Si `pending`, pollinisation longue `/wait` jusqu'au terminal.
4. À `approved`, [vérifier le jeton de décision](https://maetra.io/fr/docs/govern-api/decision-tokens),
puis la consommer à travers [autorisation d'exécution](https://maetra.io/fr/docs/govern-api/execution-receipts) immédiatement avant d'agir. Enregistrez chaque tentative et vérifiez l'effet. Sur quoi que ce soit d'autre, ne joue pas.