Skip to content

Seat the players

An actor is anything with act(actor_input) -> ActorOutput: private observation and allowed actions in, action plus spoken words out. Every seat at a table can be a different kind of actor.

Scripted baselines (BaselineCodewordsActor, BaselineTabooActor) are deterministic and seeded. They serve as opponents/partners in training and as the fallback behind every LLM seat — a match never stalls on a misbehaving model.

OpenRouterActor drives a seat from OpenRouter or any OpenAI-compatible endpoint; game-specific prompting lives in a pluggable prompter. It handles response sanitization (unrepairable output falls back to the baseline, with the raw response kept in the trace sidecar), tight reasoning budgets with per-model overrides and token accounting, and short model-authored notes-to-self between turns.

from turngames.actors import OpenRouterActor, BaselineCodewordsActor, CodewordsPrompter

actor = OpenRouterActor(
    model="anthropic/claude-haiku-4.5",
    api_key=os.environ["OPENROUTER_API_KEY"],
    fallback=BaselineCodewordsActor(seed="match-1:red_guesser_1"),
    prompter=CodewordsPrompter(),
)

Point base_url at any local OpenAI-compatible shim to seat subscription-backed models. A seat is just act() — humans fit the same interface.