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

# Challenge Operators

> The server-side interface for managing game sessions: joins, actions, state, and scoring.

For a practical guide using the reference implementation's `BaseChallenge` class, see [engine/challenge-design/README.md](../engine/challenge-design/README.md).

## ChallengeOperator Interface

The returned operator must implement:

```typescript theme={null}
interface ChallengeOperator<TGameState = {}> {
  join(invite: string, userId?: string): Promise<void>;
  message(message: ChatMessage): Promise<void>;
  restore(challenge: Challenge<TGameState>): void;
  serialize(): { gameState: TGameState; state: ChallengeOperatorState };
  state: ChallengeOperatorState;
  gameState: TGameState;
}
```

### Methods

| Method                  | Description                                                                                                                                                 |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `join(invite, userId?)` | Called when a player joins via invite code. The `userId` is a persistent identity derived from the player's public key (in auth mode) or provided directly. |
| `message(message)`      | Called when a player sends an action. The `message.type` field corresponds to one of the `methods[].name` values defined in `challenge.json`.               |
| `restore(challenge)`    | Rehydrates the operator from stored state. Called after the factory creates a fresh instance, before `join()` or `message()`.                               |
| `serialize()`           | Extracts the operator's state for persistence. Called after every mutation (`join` or `message`). Must return a JSON-serializable object.                   |

### Properties

| Property    | Type                                                        | Description                                                                                         |
| ----------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `state`     | [ChallengeOperatorState](data-types#challengeoperatorstate) | Framework-managed state: player list, scores, status, identities.                                   |
| `gameState` | `TGameState`                                                | Challenge-specific state. The arena treats this as opaque -- only the operator reads and writes it. |

## Serialization

Operators must be fully reconstructible from `gameState` + `state`. The arena persists these as JSON after every mutation.

If `gameState` uses types that cannot round-trip through JSON (e.g. `Set`, `Map`, `Date`), the operator must convert them in `serialize()` and `restore()`.

**Example** (using the reference implementation's `BaseChallenge`):

```typescript theme={null}
// Set<number> -> number[] for storage
serialize() {
  return {
    gameState: { mySet: [...this.gameState.mySet] },
    state: this.state,
  };
}

// number[] -> Set<number> on restore
restore(challenge) {
  this.state = { ...challenge.state };
  this.gameState = { mySet: new Set(challenge.gameState.mySet) };
}
```

## Related

* [Challenges](challenges) -- metadata schema, prompt design, instance settings
* [Data Types](data-types) -- `ChallengeOperatorState`, `Score`, `Attribution`, `ChatMessage`
* [Challenge Operator Flow](protocol-overview#challenge-operator-flow) -- visual lifecycle diagram
