# Lifecycle and caching

The SDK tracks binding quotes, active executions, and cache commitments separately. Your policy uses those counts to admit new work; lifecycle callbacks observe what happens after the decision.

## From quote to execution

After your policy accepts an RFQ, the SDK tracks a pending quote until Canopy awards or releases it, or it expires locally. The SDK uses the earlier of your explicit quote expiry and five seconds after the RFQ deadline.

An award replaces the pending quote with an active execution. Canopy sends the HTTP request immediately after the award notification. It does not wait for your `onAward` callback to finish.

An execution stays active through engine queueing, generation, and response streaming. Completion, cancellation, failure, or the hard execution deadline releases it. The deadline is fifteen minutes after award and covers the full HTTP exchange.

The SDK deduplicates execution IDs. An award already recorded does not increment activity or invoke `onAward` again.

## Observe lifecycle events

All lifecycle callbacks are optional and may return promises:

| Callback              | Argument                                | When it runs                                        |
| --------------------- | --------------------------------------- | --------------------------------------------------- |
| `onAward`             | `QuoteAward` plus `signal: AbortSignal` | After the SDK records a binding award               |
| `onQuoteRelease`      | `QuoteRelease`                          | When a tracked pending quote is released or expires |
| `onExecutionRelease`  | `ExecutionRelease`                      | When a tracked execution is released or expires     |
| `onCommitment`        | `Commitment`                            | When a maintained commitment arrives or is restored |
| `onCommitmentRelease` | `CommitmentRelease`                     | When a tracked commitment is released or expires    |
| `onError`             | `Error`                                 | Reports safe collection and callback errors         |

Callback errors do not revoke an award. `onAward` receives an abort signal that is cancelled on callback timeout or connection close. Use it for bounded setup or observation, not for deciding whether to accept the request. Keep callbacks short so they do not delay processing later messages.

Do not log provider tokens or engine credentials. For event fields and release reasons, see the [protocol reference](/providers/protocol#quoteaward).

## Keep cache promises

An initial cacheable award includes a provisional commitment whose expiry covers the execution deadline plus the cache TTL. After successful cache accounting, a commitment update supplies the actual maintained expiry.

Successful cached follow-ups refresh that expiry and retain the accepted prices. More than one request can use the same commitment at once. The commitment becomes an idle cached session only after its last active request ends.

Execution completion does not release a maintained cache commitment. Keep the physical cache available until the commitment expires or is invalidated. Failed initial executions release their provisional commitments.

The SDK enforces supplied deadlines locally even if a release notification is lost. Expiry does not prove that engine work has stopped; your inference server remains responsible for physical scheduling and cancellation.

## Reconnect and restore

The SDK reconnects automatically, with delays starting at 500 ms and growing to a maximum of 30 seconds. On each connection, Canopy sends maintained commitments and active executions before new routing messages. The SDK restores this state before resuming standing-price publication.

Maintained commitment expiries take precedence over provisional values from earlier awards. Failures in observer callbacks do not prevent restoration.

A disconnected agent does not imply a lost engine cache. Leave `cleanCache` unset for ordinary reconnects. Set `cleanCache: true` only when the engine's physical cache has been discarded. The SDK requests the reset on connection and returns to normal reconnect behavior after receiving restored state.

After an inference API restart, maintained commitments can be recovered from the database. Transient awards are not durable dispatch authority.

## Shut down

The CLI handles SIGINT and SIGTERM. When embedding the SDK, call `client.close()` to stop polling, close the socket, and stop reconnecting. Repeated calls return the same shutdown promise.

Closing the agent does not assert that the engine has finished all in-flight requests or erase its cache obligations. Plan engine shutdown around the work and retained cache you have promised.
