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

# Hooks de session

> Utilisez SessionHooks pour injecter des traitements dans le cycle de vie d'une session Copilot et implémenter contrôle d'exécution, audit et logique de récupération.

## Hooks de session

`hooks` permet d'injecter du code dans chaque étape du cycle de vie d'une session Copilot.
Vous pouvez ainsi ajouter le contrôle d'exécution d'outils, le journal d'audit, l'enrichissement de prompts, la gestion d'erreurs, etc., sans toucher au cœur de l'implémentation.

## Flux des hooks

```mermaid theme={null}
flowchart LR
    A[Session starts] -->|onSessionStart| B[User prompt]
    B -->|onUserPromptSubmitted| C[Pre tool]
    C -->|onPreToolUse| D[Tool execution]
    D -->|onPostToolUse| E{Continue?}
    E -->|yes| C
    E -->|no| F[Session ends]
    F -->|onSessionEnd| G((Done))
    C -. error .-> H[onErrorOccurred]
    D -. error .-> H
```

## Utilisation de base

```php theme={null}
use Revolution\Copilot\Contracts\CopilotSession;
use Revolution\Copilot\Facades\Copilot;
use Revolution\Copilot\Types\SessionHooks;
use Revolution\Copilot\Types\Hooks\ErrorOccurredHookInput;
use Revolution\Copilot\Types\Hooks\ErrorOccurredHookOutput;
use Revolution\Copilot\Types\Hooks\PostToolUseHookInput;
use Revolution\Copilot\Types\Hooks\PostToolUseHookOutput;
use Revolution\Copilot\Types\Hooks\PreToolUseHookInput;
use Revolution\Copilot\Types\Hooks\PreToolUseHookOutput;
use Revolution\Copilot\Types\Hooks\SessionEndHookInput;
use Revolution\Copilot\Types\Hooks\SessionEndHookOutput;
use Revolution\Copilot\Types\Hooks\SessionStartHookInput;
use Revolution\Copilot\Types\Hooks\SessionStartHookOutput;
use Revolution\Copilot\Types\Hooks\UserPromptSubmittedHookInput;
use Revolution\Copilot\Types\Hooks\UserPromptSubmittedHookOutput;

Copilot::start(function (CopilotSession $session) {
    $response = $session->sendAndWait(prompt: 'READMEの要点をまとめて');
    dump($response->content());
}, config: [
    'model' => 'gpt-5',
    'hooks' => new SessionHooks(
        onSessionStart: function (SessionStartHookInput $input): ?SessionStartHookOutput {
            return new SessionStartHookOutput(
                additionalContext: "Project root: {$input->cwd}",
            );
        },

        onUserPromptSubmitted: function (UserPromptSubmittedHookInput $input): ?UserPromptSubmittedHookOutput {
            if (str_starts_with($input->prompt, '/fix')) {
                return new UserPromptSubmittedHookOutput(
                    modifiedPrompt: '現在のエラーを修正して、変更点を要約して。',
                );
            }

            return null;
        },

        onPreToolUse: function (PreToolUseHookInput $input): ?PreToolUseHookOutput {
            $blocked = ['bash', 'shell', 'delete_file'];

            if (in_array($input->toolName, $blocked, true)) {
                return new PreToolUseHookOutput(
                    permissionDecision: 'deny',
                    permissionDecisionReason: "{$input->toolName} n'est pas autorisé dans cet environnement",
                );
            }

            return new PreToolUseHookOutput(permissionDecision: 'allow');
        },

        onPostToolUse: function (PostToolUseHookInput $input): ?PostToolUseHookOutput {
            if ($input->toolName === 'read_file') {
                return new PostToolUseHookOutput(
                    additionalContext: 'Si nécessaire, explorez les fichiers liés et comparez-les.',
                );
            }

            return null;
        },

        onErrorOccurred: function (ErrorOccurredHookInput $input): ?ErrorOccurredHookOutput {
            if ($input->errorContext === 'model_call' && $input->recoverable) {
                return new ErrorOccurredHookOutput(
                    errorHandling: 'retry',
                    retryCount: 2,
                    userNotification: 'Nouvelle tentative suite à une erreur temporaire du modèle.',
                );
            }

            return null;
        },

        onSessionEnd: function (SessionEndHookInput $input): ?SessionEndHookOutput {
            if ($input->reason !== 'complete') {
                return new SessionEndHookOutput(
                    sessionSummary: "Session ended with reason: {$input->reason}",
                );
            }

            return null;
        },
    ),
]);
```

## Hooks disponibles

| Hook                    | Moment de déclenchement                         | Usages principaux                                                     |
| ----------------------- | ----------------------------------------------- | --------------------------------------------------------------------- |
| `onSessionStart`        | Début de session (`new` / `resume` / `startup`) | Injection de contexte initial, surcharge de configuration             |
| `onUserPromptSubmitted` | Envoi d'un prompt utilisateur                   | Enrichissement, expansion de templates, filtrage d'entrée             |
| `onPreToolUse`          | Avant l'exécution d'un outil                    | Autoriser/refuser/demander, modifier les arguments, masquer la sortie |
| `onPostToolUse`         | Après l'exécution d'un outil                    | Modification du résultat, masquage d'infos sensibles, audit           |
| `onErrorOccurred`       | En cas d'erreur pendant la session              | Retry, notification, classification                                   |
| `onSessionEnd`          | Fin de session                                  | Nettoyage, métriques, résumé de fin                                   |

Renvoyer `null` maintient le comportement par défaut.

## Cas d'usage typiques

### 1) Contrôle des permissions (Permission control)

* Utilisez `onPreToolUse` en mode allow-list
* Les opérations destructrices déclenchent une validation humaine via `permissionDecision: 'ask'`
* Précisez la raison du refus avec `permissionDecisionReason`
* Les noms d'outils candidats se trouvent dans la liste [Outils](/fr/packages/laravel-copilot-sdk/tools) (ex. `view`, `glob`, `bash`)

### 2) Audit / conformité

* Combinez les hooks du cycle de vie pour collecter des événements d'audit
* Persistez les données collectées par ID de session

### 3) Enrichissement du prompt

* Ajoutez à `additionalContext` les infos projet (langage, framework, conventions) via `onSessionStart`
* Développez les raccourcis (`/fix`, `/test`) dans `onUserPromptSubmitted`

### 4) Filtrage des résultats

* Masquez les API keys / tokens / mots de passe dans `onPostToolUse`
* Résumez les résultats trop longs et ne renvoyez le détail qu'à la demande

### 5) Récupération d'erreur

* Dans `onErrorOccurred`, effectuez un `retry` uniquement si `model_call` et `recoverable=true`
* En cas d'erreur non récupérable, notifiez brièvement l'utilisateur via `userNotification`

### 6) Métriques de session

* Enregistrez l'heure de début dans `onSessionStart`
* Incrémentez les compteurs dans `onPreToolUse` / `onUserPromptSubmitted`
* Émettez la durée, le nombre d'outils et la raison de fin dans `onSessionEnd`

## Types d'entrée / sortie des hooks

### Entrée commune (`BaseHookInput`)

| Propriété   | Type     | Description                                |
| ----------- | -------- | ------------------------------------------ |
| `timestamp` | `int`    | Instant de déclenchement du hook (Unix ms) |
| `cwd`       | `string` | Répertoire de travail courant              |

### `PreToolUseHookInput`

| Propriété  | Type     | Description               |
| ---------- | -------- | ------------------------- |
| `toolName` | `string` | Nom de l'outil à exécuter |
| `toolArgs` | `mixed`  | Arguments prévus          |

### `PreToolUseHookOutput`

| Propriété                  | Type      | Description                   |
| -------------------------- | --------- | ----------------------------- |
| `permissionDecision`       | `?string` | `allow` / `deny` / `ask`      |
| `permissionDecisionReason` | `?string` | Raison du refus/de la demande |
| `modifiedArgs`             | `mixed`   | Arguments après modification  |
| `additionalContext`        | `?string` | Contexte supplémentaire       |
| `suppressOutput`           | `?bool`   | Masquer la sortie de l'outil  |

### `PostToolUseHookInput`

| Propriété    | Type                      | Description            |
| ------------ | ------------------------- | ---------------------- |
| `toolName`   | `string`                  | Nom de l'outil exécuté |
| `toolArgs`   | `mixed`                   | Arguments utilisés     |
| `toolResult` | `ToolResultObject\|array` | Résultat de l'outil    |

### `PostToolUseHookOutput`

| Propriété           | Type                            | Description                     |
| ------------------- | ------------------------------- | ------------------------------- |
| `modifiedResult`    | `ToolResultObject\|array\|null` | Résultat modifié                |
| `additionalContext` | `?string`                       | Contexte supplémentaire         |
| `suppressOutput`    | `?bool`                         | Masquer l'affichage du résultat |

### `UserPromptSubmittedHookInput`

| Propriété | Type     | Description                    |
| --------- | -------- | ------------------------------ |
| `prompt`  | `string` | Prompt saisi par l'utilisateur |

### `UserPromptSubmittedHookOutput`

| Propriété           | Type      | Description                       |
| ------------------- | --------- | --------------------------------- |
| `modifiedPrompt`    | `?string` | Prompt modifié                    |
| `additionalContext` | `?string` | Contexte complémentaire           |
| `suppressOutput`    | `?bool`   | Masquer l'affichage de la réponse |

### `SessionStartHookInput`

| Propriété       | Type      | Description                  |
| --------------- | --------- | ---------------------------- |
| `source`        | `string`  | `startup` / `resume` / `new` |
| `initialPrompt` | `?string` | Prompt initial               |

### `SessionStartHookOutput`

| Propriété           | Type      | Description                                        |
| ------------------- | --------- | -------------------------------------------------- |
| `additionalContext` | `?string` | Contexte initial de session                        |
| `modifiedConfig`    | `?array`  | Surcharge partielle de la configuration de session |

### `SessionEndHookInput`

| Propriété      | Type      | Description                                              |
| -------------- | --------- | -------------------------------------------------------- |
| `reason`       | `string`  | `complete` / `error` / `abort` / `timeout` / `user_exit` |
| `finalMessage` | `?string` | Message final                                            |
| `error`        | `?string` | Erreur de fin                                            |

### `SessionEndHookOutput`

| Propriété        | Type      | Description                     |
| ---------------- | --------- | ------------------------------- |
| `suppressOutput` | `?bool`   | Masquer la sortie finale        |
| `cleanupActions` | `?array`  | Infos sur le nettoyage effectué |
| `sessionSummary` | `?string` | Résumé de session               |

### `ErrorOccurredHookInput`

| Propriété      | Type      | Description                                                     |
| -------------- | --------- | --------------------------------------------------------------- |
| `error`        | `string`  | Message d'erreur                                                |
| `errorContext` | `?string` | Parmi `model_call` / `tool_execution` / `system` / `user_input` |
| `recoverable`  | `bool`    | Récupérable ou non                                              |

### `ErrorOccurredHookOutput`

| Propriété          | Type      | Description                           |
| ------------------ | --------- | ------------------------------------- |
| `suppressOutput`   | `?bool`   | Masquer l'affichage de l'erreur       |
| `errorHandling`    | `?string` | `retry` / `skip` / `abort`            |
| `retryCount`       | `?int`    | Nombre de tentatives                  |
| `userNotification` | `?string` | Notification adressée à l'utilisateur |

## ToolResultObject

Objet standard représentant le résultat d'exécution d'un outil.

| Propriété            | Type      | Description                                   |
| -------------------- | --------- | --------------------------------------------- |
| `textResultForLlm`   | `?string` | Résultat texte à transmettre au LLM           |
| `resultType`         | `?string` | `success` / `failure` / `rejected` / `denied` |
| `resultForAssistant` | `?array`  | Données de résultat destinées à l'assistant   |

## Bonnes pratiques

1. N'exécutez pas trop de traitements synchrones lourds à l'intérieur des hooks. Passez à de l'asynchrone si nécessaire.
2. Quand aucun changement n'est requis, renvoyez `null` pour laisser le comportement par défaut.
3. Explicitez autant que possible `permissionDecision`.
4. Ne masquez pas trop les erreurs critiques : conservez des chemins de log/notification.
5. Gérez l'état par ID de session et nettoyez dans `onSessionEnd`.

<Info>
  Pour les dernières informations, consultez le [dépôt GitHub](https://github.com/invokable/laravel-copilot-sdk).
</Info>


## Related topics

- [Événements de cycle de vie de session](/fr/packages/laravel-copilot-sdk/session-lifecycle-event.md)
- [⚡Introduction à Livewire 4 — créer des UI réactives sans JavaScript](/fr/blog/livewire-introduction.md)
- [Reprise de session](/fr/packages/laravel-copilot-sdk/resume.md)
- [Construire une SPA avec Inertia.js](/fr/blog/inertia-introduction.md)
- [Contexte de session et filtrage](/fr/packages/laravel-copilot-sdk/session-context.md)
