baturyilmaz/agent-office: Slack for AI Agents. Contribute to baturyilmaz/agent-office development by creating an account on Gi

github.com · 2026-08-21 · by Long Nguyen ·github
Slack for AI Agents. Contribute to baturyilmaz/agent-office development by creating an account on GitHub.

baturyilmaz/agent-office

Slack for AI Agents. Contribute to baturyilmaz/agent-office development by creating an account on GitHub.

0 stars · 0 forks

README

agent-office Multi-agent workspace manager built on Pi. Orchestrates AI coding agents — similar to Claude Code or OpenClaw — with tick-based scheduling, priority queues, inbox IPC, cross-agent file access, watchdog monitoring, proactive cron jobs, optional Docker sandbox isolation, and declarative YAML configuration.

agent-office.mp4

Get Started Try one of these examples to get up and running quickly. Set env vars in the project root .env (not inside Docker — the host forwards them to containers). Basic team — PM, coder, and reviewer (uses GitHub Copilot OAuth, no API keys): pnpm install cp -r examples/basic-team/ ~/.agent-office/offices/basic-team/ pnpm dev oauth login github-copilot --office basic-team pnpm dev start --office basic-team --sandbox docker OpenServ team — idea scout, team lead, agent dev, and token launcher: pnpm install cp .env.example .env mkdir -p ~/.agent-office/offices/openserv-team cp examples/openserv-team/office.yaml ~/.agent-office/offices/openserv-team/office.yaml pnpm dev start --office openserv-team --sandbox docker OPENAI_API_KEY= WALLET_PRIVATE_KEY= # EVM wallet key for openserv-labs/skills agents Feature team — task-driven development with Kanban board: cp -r examples/feature-team/ ~/.agent-office/offices/feature-team/ pnpm dev start --office feature-team See examples/ for more details — each has a README describing the setup. Table of Contents

Architecture Quick Start OAuth Authentication

Supported Providers CLI Commands Using OAuth in office.yaml Web UI Auth Selector

Multi-Office Architecture

Creating an Office Office Configuration Heartbeat Permissions Tool Policy Hierarchy Auto-Sync Reload Cron Jobs Office-Level Cron Agent Cron Tools Task Management Migration from agents.yaml

Sandbox Modes

In-Process Mode Docker Sandbox Mode

Commands

Hire Options CLI Flags Execution Surfaces REST API Endpoints

Agent Tools

list_agents message_agent message_user post_channel read_agent_file authenticated_fetch cron_add cron_remove cron_list read_skill skill_search skill_install skill_remove skill_create task_create task_update task_list task_get task_delete Tool Architecture Prompt System

Concepts

Tick-Based Scheduler Priority Levels Workspace Sandboxing Skills Watchdog Message Persistence

Prompt Inspection Cost Tracking Web UI End-to-End Examples Project Structure Dependencies Development

Architecture

graph TD YAML[office.yaml] --> WS CLI[CLI + Web UI] --> WS[Workspace]

WS --> SCH[Scheduler\ntick loop] WS --> BUS[MessageBus\ninboxes] WS --> WD[Watchdog\nheartbeat] WS --> CRON[CronService\nscheduled jobs] WS --> TS[TaskService\nKanban board]

WS -->|in-process| A[Agent A\nPi · tools · skills] WS -->|in-process| B[Agent B\nPi · tools · skills]

WS -->|Docker sandbox| HA[Host API\nHTTP :13000] HA <-->|HTTP| SA[Sandbox A\nDocker · Pi · proxy tools] HA <-->|HTTP| SB[Sandbox B\nDocker · Pi · proxy tools]

BUS --> A BUS --> B BUS --> HA

Loading

Core flow: office.yaml (auto-spawn) / CLI / Web UI / Cron / Agent cron tools / Task notifications -> Workspace -> Scheduler tick -> drain inbox -> dispatch to Pi Agent -> agent runs tools -> response streamed to UI. Each agent is a full Pi coding agent with its own filesystem workspace, skills, and injected tools (message_user, post_channel, message_agent, list_agents, read_agent_file, authenticated_fetch, cron_add, cron_remove, cron_list, task_create, task_update, task_list, task_get, task_delete, read_skill, skill_search, skill_install, skill_remove, skill_create). The scheduler runs a tick loop that serves agents by priority, one message per tick per agent, non-blocking. Agents can run in-process (default) or inside Docker containers for full process-level isolation. Quick Start pnpm install

Configure .env

cp .env.example .env # then fill in your keys

Create an office

pnpm dev office create my-team

Start (Web UI auto-starts)

pnpm dev start --office my-team

Start with Docker sandbox isolation

pnpm dev start --office my-team --sandbox docker Create a .env file with your provider API keys. Each model requires its corresponding provider key:

Model API Keys (required for agents using these models)

OPENAI_API_KEY=sk-... # For OpenAI models (gpt-4o, etc.) ANTHROPIC_API_KEY=sk-... # For Anthropic models (Claude, etc.) GEMINI_API_KEY=... # For Google Gemini models XAI_API_KEY=... # For xAI Grok models

Optional: Custom secret refs for office.yaml agents

MY_GH_TOKEN=ghp_... # Host env vars for authenticated_fetch secrets

Authentication: Each model needs credentials. You can use either API keys (.env) or OAuth:

API keys — set in .env (e.g. OPENAI_API_KEY=sk-...). Required when the model's provider has no OAuth credentials. OAuth — authenticate via provider CLIs before starting. OAuth tokens auto-refresh and don't require .env keys.

Option A: API keys in .env

echo "ANTHROPIC_API_KEY=sk-..." >> .env

Option B: OAuth login (requires provider CLI installed)

pnpm dev oauth login anthropic --office my-team pnpm dev oauth list --office my-team When both OAuth credentials and an API key exist for a provider, you can switch between them per-agent in the Web UI. See OAuth Authentication for details. See the Dynamic Model Discovery section below for how to browse available models and their requirements in the Web UI. OAuth Authentication As an alternative to API keys in .env, agents can authenticate with model providers via OAuth. This uses the provider's own CLI login flow — the agent-office CLI orchestrates the browser-based OAuth handshake and stores credentials per office. Supported Providers

Provider ID Name Flow Type Requires

anthropic Anthropic Code paste Anthropic CLI

openai-codex OpenAI Callback server OpenAI Codex CLI

github-copilot GitHub Copilot Code paste GitHub Copilot CLI

google-gemini-cli Google Gemini CLI Callback server Gemini CLI

google-antigravity Antigravity Callback server Antigravity CLI

Code paste providers open a browser URL and prompt you to paste back an auth code. Callback server providers start a local HTTP server and complete the flow automatically. CLI Commands

Login — interactive OAuth flow (opens browser)

pnpm dev oauth login <provider> --office <id>

List — show all providers and credential status

pnpm dev oauth list --office <id>

Logout — remove stored credentials

pnpm dev oauth logout <provider> --office <id> Example session: $ pnpm dev oauth login anthropic --office my-team [oauth] Logging in to Anthropic... [oauth] Open this URL to authenticate: https://console.anthropic.com/oauth/... Paste the authorization code: ** [oauth] Credentials saved for Anthropic.

$ pnpm dev oauth list --office my-team ✓ anthropic Anthropic ✗ openai-codex OpenAI ✗ github-copilot GitHub Copilot ✗ google-gemini-cli Google Gemini CLI ✗ google-antigravity Antigravity

Login: pnpm dev oauth login <provider> --office my-team Logout: pnpm dev oauth logout <provider> --office my-team Credentials are stored at ~/.agent-office/offices/<id>/oauth/<provider>.json and auto-refresh when tokens expire. Using OAuth in office.yaml Set the auth field on an agent to use OAuth instead of an API key: agents: designer: model: anthropic:claude-sonnet-4-20250514 auth: "oauth:anthropic" # use OAuth credentials reviewer: model: openai:gpt-4o auth: "oauth:openai-codex" # use OAuth credentials analyst: model: google:gemini-2.0-flash # no auth field — falls back to GEMINI_API_KEY from .env The auth field format is oauth:<provider-id>. When set, the agent uses stored OAuth credentials with automatic token refresh instead of a static API key. Web UI Auth Selector When OAuth credentials exist for an agent's model provider, the Web UI Config tab shows an Auth selector to switch between "API Key" and "OAuth" modes. The UI also displays all authenticated providers as green badges with one-click removal. The auth selector only appears when credentials are available — if no OAuth login has been done for a provider, agents use API keys by default. OAuth REST API

Method Path Description

GET /api/oauth/providers List all providers with authentication status

GET /api/oauth/status/:id Check if credentials exist for a provider

DELETE /api/oauth/:id Remove stored credentials for a provider

Multi-Office Architecture Each office represents a company or team with shared identity, env vars, and secrets. Offices live under ~/.agent-office/offices/<id>/. Creating an Office

Create with default display name (same as id)

pnpm dev office create acme

Create with a custom display name

pnpm dev office create acme --name "Acme Corp" Office IDs must be path-safe: lowercase letters, digits, hyphens, underscores (matching [a-z0-9][a-z0-9_-]*). The display name (office.name in YAML) is free-form. Office Configuration (office.yaml) Define your office once in ~/.agent-office/offices/<id>/office.yaml and agents auto-spawn on startup.

~/.agent-office/offices/acme/office.yaml

office: name: Acme Corp description: "We build AI-powered widgets" env: SHARED_API_URL: https://api.acme.com secrets: SHARED_TOKEN: ${ACME_TOKEN} cron: standup: schedule: "0 9 1-5" report_channel: general tasks: - title: "Daily standup" assignee: pm

agents: designer: model: anthropic:claude-sonnet-4-20250514 priority: normal # idle | low | normal | high | critical (or 0-4) thinking: low # off | minimal | low | medium | high | xhigh description: "Frontend designer — builds HTML/CSS" prompt_inline: | You are a frontend designer specializing in responsive layouts. Focus on clean, semantic HTML and modern CSS. skills: - nichochar/web-skills auth: "oauth:anthropic" # optional — use OAuth instead of API key api_key_ref: MY_CUSTOM_KEY # optional — host env var name for model key override env: # non-sensitive, passed as Docker --env (agent overrides office) LOG_LEVEL: debug WORKSPACE_NAME: designer secrets: # sensitive, ${VAR} refs only — delivered via authenticated_fetch GITHUB_TOKEN: ${MY_GH_TOKEN} disclose_secrets: true # show secret names in system prompt (default: false) permissions: office_cron: true # allow managing office-level cron jobs

reviewer: model: openai:gpt-4.1 priority: high thinking: medium description: "Code reviewer" Office-level env and secrets are inherited by all agents. Agent-level values override office-level. All agent fields are optional. Agents are spawned sequentially in declaration order; if one fails, the rest still start. Model availability depends on your provider account — replace the model value with your preferred provider:model-id if the default is unavailable.

Field Type Default Description

model string anthropic:claude-sonnet-4-20250514 provider:model-id

priority string | number normal Priority name or 0-4

thinking string low off / minimal / low / medium / high / xhigh

description string "" Visible to other agents

prompt_inline string (none) Custom instructions (inline text, appended to base prompt)

cwd string ~/.agent-office/offices/<id>/agents/<name>/workspace Working directory

skills string[] [] GitHub sources to auto-install (owner/repo)

auth string (none — uses API key) Auth mode: oauth:<provider-id> for OAuth (see OAuth)

api_key_ref string (auto from provider) Host env var name for model API key

env map {} Non-sensitive env vars (Docker --env, supports ${VAR} refs)

secrets map {} Secret refs in ${VAR} format (delivered via authenticated_fetch)

disclose_secrets boolean false Show secret names in system prompt

cron map {} Named cron jobs (see Cron Jobs)

reports_to string (none — reports to user) Name of manager agent (see Hierarchy)

permissions map {} Agent permissions (see Permissions, Tool Policy)

prompt_mode string "full" full (all blocks) or minimal (base + identity + custom only)

on_demand_skills boolean true Advertise skill summaries; load full content on demand via read_skill

heartbeat map (none) Proactive heartbeat config (see Heartbeat)

Task tools (task_create, task_update, task_list, task_get, task_delete) are available to all in-process agents by default. Restrict access via permissions.tools.deny. See Task Management. Heartbeat Agents can run proactively via heartbeats — periodic messages that prompt agents to check for work or run maintenance without external triggers. agents: monitor: heartbeat: interval_ms: 60000 prompt: "Check for pending work and report status" active_hours: start: "09:00" end: "17:00"

Field Required Default Description

interval_ms yes — Interval in milliseconds between heartbeats

prompt no (default) Custom prompt text for heartbeat messages

active_hours no (none) Restrict heartbeats to a time window

Heartbeat messages are injected with from: "_heartbeat_" and formatted as [Heartbeat]\n<prompt>. Busy agents (status running) are skipped. Permissions The permissions field controls which privileged operations an agent may perform:

Permission Type Default Description

office_cron boolean false Allow managing office-level cron jobs via cron_add/cron_remove

Permissions are validated at config parse time. Unknown keys or non-boolean values are rejected. Tool Policy The permissions.tools field restricts which tools an agent may use: agents: restricted-bot: permissions: tools: deny: [cron_add, cron_remove] # blacklist — all except these # OR # allow: [message_agent, list_agents] # whitelist — only these

deny — blacklist: agent has all tools except the listed ones. allow — whitelist: agent has only the listed tools. Cannot specify both allow and deny — validation error at parse time. Default (no tools field): all tools available. Server-side enforcement: in Docker sandbox mode, denied tools also return HTTP 403 on the corresponding Host API endpoint (e.g. /api/cron-add returns 403 Tool denied by policy).

Permission Management Defaults: office_cron is false; tools are all allowed unless allow or deny is set. Setting both allow and deny is a validation error. View permissions in the Web UI or edit via the API without editing YAML manually: agent permission show bot agent permission set bot office_cron true agent permission set bot tools deny cron_add,cron_remove agent permission clear bot office_cron agent permission clear bot tools Changes are saved to office.yaml. Run office reload --force to apply. Hierarchy The reports_to field defines a manager for each agent, creating an org tree. Agents without reports_to report directly to the user. The hierarchy is injected into the system prompt so each agent knows its manager, peers, and direct reports. agents: lead: description: "Team lead" coder: reports_to: lead reviewer: reports_to: lead Validation rules:

Must reference a valid agent name (same [a-zA-Z0-9_-]+ format) Self-reference is rejected Cycles are detected and rejected (e.g. A reports to B, B reports to A) Unknown agent references are rejected

Hierarchy changes trigger agent restarts (prompts are recomposed with updated context). Auto-Sync Commands automatically keep office.yaml in sync:

hire persists the agent to YAML (use --ephemeral to skip) fire removes the agent from YAML skill add/remove updates the agent's skills array in YAML (GitHub source model)

skills.sh package installs (skill_search / skill_install tools or UI install) write files under agents/<agent>/skills but do not auto-edit office.yaml. All writes are atomic (temp file + rename) and serialized through a two-layer lock (in-process queue + cross-process file lock) per office. Reload

API command strings (UI has equivalent controls):

office reload # Spawn new agents from YAML, skip already-running office reload --force # Kill and re-spawn agents with changed config office validate # Dry-run: parse + validate without spawning office path # Print path to office.yaml Cron Jobs Agents can run proactively on schedules via per-agent cron jobs. The host-side CronService manages timers and creates structured tasks via TaskService — giving cron-triggered work full Kanban visibility, dependency chaining, and completion reporting.

Breaking change: message and targets fields have been replaced by a tasks array. Each task requires title and assignee.

In office.yaml under the agents section:

agents: standup-bot: model: anthropic:claude-sonnet-4-20250514 cron: daily-standup: schedule: "0 9 1-5" # 5-field only (min hour dom month dow) timezone: "America/New_York" # optional, default UTC catch_up: once # optional: "skip" (default) | "once" enabled: true # optional, default true report_channel: general # optional, post completion summary to this channel tasks: - title: "Daily standup report" description: "Report your status for today's standup" assignee: standup-bot

Field Required Default Description

schedule yes — 5-field cron expression (@daily/@hourly rejected)

tasks yes — Array of task templates; each requires title and assignee

timezone no UTC IANA timezone for schedule evaluation

catch_up no skip skip = ignore missed fires on restart; once = fire one catch-up task

enabled no true Set false to pause without removing

report_channel no (none) Channel name to post task completion summaries to

Each task in the tasks array supports:

Field Required Description

title yes Task title shown in Kanban board

assignee yes Agent name to assign the task to

description no Detailed instructions for the assignee

parent_id no Parent task ID (T-prefixed) to nest under

report_channel no Per-task channel override for completion notification

Job names must match [a-zA-Z0-9_-]+. Each agent can have 0-N named jobs (max 10 per agent via tools). Task chaining: Multiple tasks in a single cron job are automatically chained — each task depends on the previous one completing. The chain fires with CRITICAL priority. Catch-up behavior: On restart, if catch_up: once and a fire was missed since the last run, one immediate task chain is created. First-ever run (no prior state) never catches up. State persists to ~/.agent-office/offices/<id>/cron/state.json. Safety guards: Tasks are always created regardless of agent status — they queue in the agent's inbox. A global dispatch cap of 60 cron jobs per minute prevents misconfigured schedules from flooding the task queue. Cron Commands

API command strings (UI has equivalent controls):

cron list # List all cron jobs cron status [agent] # Detailed job status cron add <agent> <job> "<schedule>" [--apply] # Add a job (prompts for task title/assignee) cron remove <agent> <job> [--apply] # Remove a job cron trigger <agent> <job> # Fire immediately cron enable <agent> <job> [--apply] # Re-enable a paused job cron disable <agent> <job> [--apply] # Pause a job Without --apply, commands write to office.yaml only — run office reload to activate. With --apply, changes take effect immediately if the agent is running. Change detection uses normalized config comparison (resolved model, numeric priority, sorted skills, trimmed prompt) so cosmetic YAML differences like normal vs 2 or reordered skills don't trigger false warnings. Office-Level Cron In addition to per-agent cron, you can define office-level cron jobs that create task chains across mul

source

github.com · 1 images · 1 videos · 102 links

Comments (0)

No comments yet