Skip to content

Demos

Honeybee includes two complete demo games that showcase multi-agent coordination in action.

Each demo is 4 files in demos/<name>/:

FilePurpose
brood.yamlAgent configuration (provider, roles, agent types)
<name>.acp.yamlACP protocol (roles, phases, state, events)
<name>.jsDance file (game logic, state machine, tool handlers)
index.htmlWeb UI (WebSocket events, game controls)

A chess game where you play White against an AI opponent (Black).

Terminal window
wgl serve --port=8080 --verbose \
--brood=demos/chess/brood.yaml \
--dances=demos/chess/chess.js \
--static=demos/chess

Navigate to http://localhost:8080/ (or https:// with TLS certs).

  • White (human) clicks to make moves via the UI
  • The UI sends dance_call messages over WebSocket
  • The dance file validates moves and updates the board
  • Black (AI) wakes on turn.black events, thinks, and calls make_move
  • Board state is shared via ACP set_state
demos/chess/brood.yaml
provider: cerebras/gpt-oss-120b
hives:
main:
acp: chess.acp.yaml
agents:
- role: white
agents: 0 # human-controlled
- role: black
type: drone

agents: 0 means no AI agent is spawned for that role — the UI controls it directly via dance_call.

6 players (1 human + 5 AI) in a social deduction game with hidden roles.

Terminal window
wgl serve --port=8080 --verbose \
--brood=demos/werewolf/brood.yaml \
--dances=demos/werewolf/werewolf.js \
--static=demos/werewolf
  • Night: Werewolves vote to eliminate. Seer investigates.
  • Day: All players discuss (freeform text). Accusations, defenses, alliances.
  • Vote: Players vote to eliminate a suspect. Majority wins.
  • Cycle repeats until werewolves or villagers win.

No agent knows the full game state. Werewolves know each other but must blend in. The seer knows one identity per night but must be careful revealing it. Emergent behaviors:

  • Werewolves deflect suspicion
  • The seer drops hints without revealing their role
  • Villagers form voting blocs
  • Agents reference previous rounds and track voting patterns

All from simple role descriptions + ACP events.

acp: "1.0"
name: my-game
roles:
player:
count: 4
model_hint: "cerebras/llama-3.3-70b"
phases:
setup: { exit_condition: { event: start } }
playing: { exit_condition: { state_key: phase, equals: done } }
export function inject({ state, agent }) {
return `You are ${agent.role}. Game state: ${state.get('status')}`;
}
export const take_action = {
description: 'Take a game action',
params: { action: { type: 'string' } },
handler: async ({ args, state, acp }) => {
await acp.setState('last_action', args.action);
await acp.publish('action.taken', { action: args.action });
return { result: { success: true } };
},
};
provider: cerebras/llama-3.3-70b
hives:
main:
acp: my-game.acp.yaml
agents:
- role: player
agents: 0 # human-controlled

The UI connects via WebSocket and drives state from events:

const ws = new WebSocket('ws://localhost:8080/ws');
ws.onmessage = (e) => {
const msg = JSON.parse(e.data);
if (msg.type === 'state_changed') updateDisplay(msg);
if (msg.type === 'dance_result') handleResult(msg);
};
// Player action
function sendAction(action) {
ws.send(JSON.stringify({
type: 'dance_call',
tool: 'take_action',
args: { action },
agentId: 'player-1',
role: 'player',
callId: crypto.randomUUID(),
}));
}
  • WS events are primary: Drive all UI state from WebSocket events, not REST polling
  • Publish start event: The orchestrator waits for a start event before spawning AI agents
  • Reset before play: Hit Reset to clear state when restarting a game
  • “Waiting” not “DONE”: Non-active agents should say “Waiting” — “DONE” triggers runner termination
  • Per-player events: Use turn.player_2 (not turn) so only the relevant agent wakes