Workspaces¶
Workspaces are isolated agent instances with their own personality, configuration, and capabilities. Each workspace represents a distinct AI agent with specific behavior patterns and access permissions.
Directory Structure¶
agent_workspaces/<name>/
├── agent/ # Identity and extensions
│ ├── AGENT.md # Capabilities, behavior guidelines
│ ├── USER.md # User context/preferences
│ ├── SOUL.md # Core personality, values
│ ├── HEARTBEAT.md # Session state scratchpad (agent-writable)
│ ├── tools/ # Custom LangChain @tool functions
│ │ ├── *.py
│ │ └── requirements.txt
│ └── skills/ # Reusable knowledge and behavior patterns
│ └── <skill-name>/
│ └── SKILL.md
├── config/ # Configuration (write-protected from agent)
│ ├── agent.yaml # Per-workspace settings (model, channel, queue)
│ ├── .env # API keys and secrets
│ └── crons/ # Scheduled task definitions
│ └── *.yaml
├── data/ # Framework-managed state (write-protected from agent)
│ ├── conversations.db # AsyncSqliteSaver checkpoint database
│ ├── sessions.json # Session/conversation thread state
│ ├── token_usage.jsonl # Token usage metrics (append-only)
│ ├── subagents.yaml # Sub-agent state
│ ├── TASKS.yaml # Persistent task tracking
│ ├── dynamic_crons.json # Agent-scheduled tasks
│ ├── heartbeat_log.jsonl # Heartbeat event log
│ └── uploads/ # User-uploaded files (from FilePersistenceProcessor)
│ └── {YYYY-MM-DD}/ # Date-partitioned storage
│ ├── report.pdf # Original uploaded file
│ ├── report.md # Docling-converted markdown (sibling)
│ ├── voice_123.ogg # Original audio file
│ └── voice_123.txt # Whisper transcript (sibling)
├── memory/ # Archived conversations and session logs
│ ├── conversations/ # Conversation exports (markdown + JSON)
│ │ ├── conv_*.md # Markdown archives (human-readable)
│ │ └── conv_*.json # JSON sidecars (machine-readable)
│ └── logs/ # Heartbeat, cron, and sub-agent session logs
│ ├── heartbeat/
│ ├── cron/
│ └── subagent/
└── workspace/ # Agent work area (default write target)
├── downloads/ # Browser-downloaded files
└── screenshots/ # Browser screenshots
Required Files¶
Every workspace must contain four markdown files that define the agent's identity and behavior.
AGENT.md - Capabilities and Behavior¶
Defines what the agent can do and how it should behave.
Example:
# Agent Profile
You are Gilfoyle, a senior systems architect and DevOps engineer.
## Capabilities
- AWS infrastructure management (Lambda, S3, DynamoDB)
- Python development (FastAPI, SQLAlchemy, Pydantic)
- Terraform infrastructure-as-code
- CI/CD pipeline design
- System architecture and design patterns
## Communication Style
- Be direct and technically precise
- Avoid unnecessary pleasantries
- Use sarcasm sparingly but effectively
- Cite specific technologies and patterns when relevant
## Constraints
- Do not make AWS changes without confirmation
- Always explain architectural decisions
- Prioritize security and scalability
USER.md - User Context¶
Information about the user(s) this agent serves.
Example:
# User Profile
## Name
John Sosoka
## Role
Engineering Lead
## Preferences
- Prefers concise technical explanations
- Works in Pacific Time (PT)
- Uses AWS us-west-2 region by default
## Context
- Manages multiple client projects
- Values clean, maintainable code
- Follows Clean Code and Clean Architecture principles
SOUL.md - Core Personality¶
The agent's fundamental values and personality traits.
Example:
# Core Values
## Technical Excellence
Always prioritize correctness, clarity, and maintainability over cleverness.
## Honesty
If you don't know something, say so. Don't speculate or guess about critical systems.
## Efficiency
Value the user's time. Be concise but complete.
## Professionalism
Maintain professional communication standards. You represent the engineering team.
HEARTBEAT.md - Current State¶
Session state and notes. The agent can read and modify this file to persist information across conversations.
Example:
# Current State
## Session Started
2026-02-05
## Active Projects
- OpenPaw: Multi-channel agent framework
- ClientX: AWS Lambda migration
## Pending Tasks
- Review OpenPaw documentation
- Update Terraform modules for ClientX
## Recent Learnings
- Conversation persistence via AsyncSqliteSaver
- APScheduler for cron implementation
The agent can update HEARTBEAT.md during conversations to track ongoing work, decisions, and context. This file serves as a scratchpad for agent-maintained notes and is especially useful for heartbeat check-ins.
Optional Configuration¶
agent.yaml - Workspace Configuration¶
Place at config/agent.yaml to override global configuration for this specific workspace.
Example:
name: Gilfoyle
description: Sarcastic systems architect
timezone: America/Denver # IANA timezone identifier (default: UTC)
model:
provider: anthropic
model: claude-sonnet-4-20250514
api_key: ${ANTHROPIC_API_KEY}
temperature: 0.5
max_turns: 50
channel:
type: telegram
token: ${TELEGRAM_BOT_TOKEN}
allowed_users: [123456789]
allowed_groups: []
queue:
mode: steer
debounce_ms: 500
builtins:
allow: [] # Empty = allow all available
deny:
- elevenlabs
heartbeat:
enabled: true
interval_minutes: 30
active_hours: "09:00-17:00" # Interpreted in workspace timezone
suppress_ok: true
output:
channel: telegram
chat_id: 123456789
See the main CLAUDE.md documentation for detailed configuration options.
.env - Environment Variables¶
Workspace-specific environment variables are automatically loaded from config/.env.
Example:
# API keys specific to this workspace
CALENDAR_API_KEY=abc123
JIRA_API_TOKEN=xyz789
# Workspace-specific configuration
DEFAULT_PROJECT=ClientX
TEAM_EMAIL=team@example.com
These variables are available to custom tools and can be referenced in agent.yaml using ${VAR_NAME} syntax.
Workspace Isolation¶
Each workspace is fully isolated:
- Separate channels - Own Telegram bot or dedicated channel
- Independent queue - Own queue manager and concurrency limits
- Isolated filesystem - Can only read/write within workspace directory
- Dedicated agent instance - Own LangGraph agent with separate memory
- Per-workspace crons - Scheduled tasks scoped to workspace
- Isolated sub-agents - Background workers managed per workspace
- Protected framework internals -
data/andconfig/directories are write-protected from agents
This enables running multiple agents simultaneously without interference:
Each agent operates independently with its own configuration and personality.
Filesystem Access¶
Agents have sandboxed filesystem access to their workspace directory via FilesystemTools in openpaw/agent/tools/filesystem.py.
Available Operations¶
ls- List directory contentsread_file- Read file contents (100K character safety valve)write_file- Create new files or append to existing filesoverwrite_file- Replace file contents entirelyedit_file- Make precise edits to existing filesglob_files- Find files by pattern (e.g.,*.md,**/*.py)grep_files- Search file contents with regex (supportscontext_linesfor surrounding context)file_info- Get metadata (size, line count, binary detection) without reading content
Path Security¶
All filesystem operations use resolve_sandboxed_path() from openpaw/agent/tools/sandbox.py for path traversal protection:
- Workspace-scoped - Cannot access files outside workspace directory
- No absolute paths - Rejects paths starting with
/or~ - No parent traversal - Rejects
..in paths - Framework protection - Cannot write to
data/orconfig/directories
Example Use Cases¶
Persistent notes:
Data organization:
File analysis:
Uploaded file processing:
Custom Tools¶
Workspaces can define custom LangChain tools in the agent/tools/ directory. These are Python files containing @tool decorated functions that are automatically loaded and made available to the agent.
Creating Custom Tools¶
Example: Calendar tool (agent/tools/calendar.py)
from langchain_core.tools import tool
from datetime import datetime, timedelta
import os
@tool
def get_upcoming_events(days_ahead: int = 7) -> str:
"""Get upcoming calendar events.
Args:
days_ahead: Number of days to look ahead
Returns:
Formatted list of events.
"""
api_key = os.getenv("CALENDAR_API_KEY")
if not api_key:
return "Error: CALENDAR_API_KEY not configured"
# Implementation here
events = fetch_calendar_events(api_key, days_ahead)
return format_events(events)
@tool
def check_availability(date: str) -> str:
"""Check if a specific date is free.
Args:
date: Date in YYYY-MM-DD format
Returns:
Availability status with free time blocks.
"""
# Implementation here
return check_calendar_availability(date)
Tool Dependencies¶
Add a agent/tools/requirements.txt for tool-specific packages:
Missing dependencies are automatically installed at workspace startup.
Tool Loading¶
- Files must be in
{workspace}/agent/tools/*.py - Use LangChain's
@tooldecorator fromlangchain_core.tools - Tools are merged with framework builtins (brave_search, cron, browser, etc.)
- Environment variables from workspace
.envare available - Multiple tools per file are supported
- Files starting with
_are ignored - Tools are dynamically imported at workspace startup
Tool Best Practices¶
- Clear documentation - Use comprehensive docstrings with Args/Returns sections
- Error handling - Return error messages rather than raising exceptions
- Environment variables - Use
.envfor API keys and configuration - Type hints - LangChain uses type hints for parameter validation
- Focused functionality - Each tool should have a single, clear purpose
- Examples in docstring - Help the agent understand when to use the tool
Skills¶
Skills are reusable knowledge documents or behavioral patterns. Each skill lives in its own subdirectory under agent/skills/ and is defined by a SKILL.md file. Skills are loaded at workspace startup and injected into the agent's system prompt as a <skills> XML block.
Directory Structure¶
agent/skills/
├── research-patterns/
│ └── SKILL.md
├── code-review/
│ └── SKILL.md
└── _disabled-skill/ # Skipped (underscore prefix)
└── SKILL.md
SKILL.md Format¶
Skills support optional YAML frontmatter followed by markdown content:
---
name: research-patterns
description: Patterns for conducting technical research across multiple sources
version: "1.0"
---
# Research Patterns
When conducting research, follow these steps:
1. Identify primary sources...
2. Cross-reference findings across at least three independent sources...
3. Summarize findings with citations...
Frontmatter fields:
| Field | Required | Description |
|---|---|---|
name |
No | Display name (falls back to directory name) |
description |
No | Short description, truncated to 1024 chars |
version |
No | Optional version string (not used by framework) |
Key Behaviors¶
- Skills are loaded at workspace startup
- Full content is injected into the system prompt as a
<skills>XML block - Directories prefixed with
_are skipped (useful for disabling a skill without deleting it) - If no frontmatter is present, the entire file becomes the content with the directory name as skill name
- Invalid YAML frontmatter degrades gracefully (logged warning, falls back to directory name)
- Empty or missing
agent/skills/directory is silently ignored
Example: Writing Style Skill¶
agent/skills/writing-style/SKILL.md:
---
name: writing-style
description: House style guide for all written output
---
# Writing Style Guide
## Tone
- Direct and professional — no filler phrases ("Certainly!", "Great question!")
- Use active voice; avoid passive constructions where possible
- Prefer concrete nouns and specific verbs over vague generalities
## Formatting
- Use bullet points for lists of three or more items
- Code examples belong in fenced code blocks with language tags
- Section headers use title case
Scheduled Tasks (Crons)¶
Define scheduled tasks in the config/crons/ directory using YAML files.
Example: config/crons/daily-summary.yaml
name: daily-summary
schedule: "0 9 * * *" # 9 AM daily (workspace timezone)
enabled: true
prompt: |
Generate a daily summary by reviewing:
- Active projects in HEARTBEAT.md
- TASKS.yaml for pending work
- Recent conversation archives in memory/conversations/
Provide a concise status update focusing on what requires attention today.
output:
channel: telegram
chat_id: 123456789
Schedule Format:
- Standard cron expression: "minute hour day-of-month month day-of-week"
- Fires in the workspace timezone
- Examples:
- "0 9 * * *" - Every day at 9:00 AM
- "*/15 * * * *" - Every 15 minutes
- "0 0 * * 0" - Every Sunday at midnight
- "0 9 * * 1-5" - Weekdays at 9:00 AM
Enable/Disable: Set enabled: false to disable without deleting the file.
Agents can also schedule their own follow-up actions at runtime. See Scheduling for the full scheduling reference including dynamic scheduling tools.
Heartbeats¶
Heartbeats enable proactive agent check-ins on a configurable schedule. HEARTBEAT.md serves as the agent's scratchpad for tracking what to check during each heartbeat cycle — the agent reads and updates it during normal conversations.
See Scheduling for heartbeat configuration, the HEARTBEAT_OK protocol, active hours, and pre-flight skip behavior.
Conversation Memory¶
Conversations persist across restarts via durable checkpointing. The memory/conversations/ directory stores archived conversations in dual format — markdown for human reading and JSON for machine processing.
Key commands:
/new— Archive current conversation and start fresh/compact— Summarize conversation, archive it, and start new with summary injected- Auto-compact triggers automatically when context window fills up
Agents can read archived conversations via read_file() to maintain long-term memory across conversation resets. See Concepts for a deeper look at how conversation memory works.
Creating a New Workspace¶
The fastest way to create a workspace is with the init command:
# Basic scaffold with TODO markers
poetry run openpaw init my_agent
# Pre-configure model and channel
poetry run openpaw init my_agent --model anthropic:claude-sonnet-4-20250514 --channel telegram
# Scaffold in a custom directory
poetry run openpaw init my_agent --path /path/to/workspaces
This creates the workspace directory with the full 5-directory structure (agent/, config/, data/, memory/, workspace/) and pre-populates required files with templates and TODO markers.
After scaffolding:
- Edit
config/agent.yamlwith your model and channel settings - Add API keys to
config/.env - Customize
agent/AGENT.md,agent/USER.md, andagent/SOUL.mdto define personality - Optionally add custom tools in
agent/tools/and cron jobs inconfig/crons/ - Optionally add skills in
agent/skills/for reusable knowledge patterns - Run the workspace:
List available workspaces:
Name requirements: Workspace names must be 2-64 characters, start with a lowercase letter, and contain only lowercase letters, digits, hyphens, and underscores (e.g., my_agent, test-bot, gilfoyle).
Example Workspaces¶
Technical Support Agent¶
AGENT.md:
# Technical Support Specialist
You are a technical support specialist for SaaS products.
## Capabilities
- Troubleshooting common issues
- API debugging assistance
- Documentation lookup via brave_search
- Issue escalation when needed
## Communication Style
- Patient and helpful
- Ask clarifying questions
- Provide step-by-step solutions
- Link to relevant documentation
agent.yaml:
queue:
mode: followup # Process support requests sequentially
builtins:
allow:
- brave_search # Enable documentation search
- send_message # Progress updates during troubleshooting
Scheduled Reporter¶
AGENT.md:
# Daily Reporter
You generate daily reports by analyzing system state and recent activity.
## Capabilities
- Reading workspace files (HEARTBEAT.md, TASKS.yaml)
- Summarizing project status
- Identifying pending tasks and blockers
- Analyzing conversation archives for trends
config/crons/daily-report.yaml:
name: daily-report
schedule: "0 9 * * 1-5" # Weekdays at 9 AM
enabled: true
prompt: |
Review all workspace files and generate a status report.
Include:
- Active projects from HEARTBEAT.md
- Task status from TASKS.yaml
- Recent conversation topics from memory/conversations/
- Any blockers requiring human attention
Multi-User Team Assistant¶
AGENT.md:
# Team Assistant
You are a team assistant supporting multiple engineers in a group chat.
## Capabilities
- Task tracking via TASKS.yaml
- Calendar management (custom tools)
- Documentation lookup
- Meeting note summarization
## Communication Style
- Tag users when addressing them directly
- Be concise in group contexts
- Use threads for detailed discussions
agent.yaml:
channel:
type: telegram
allowed_groups: [-1001234567890] # Team group chat
builtins:
task_tracker:
enabled: true
brave_search:
enabled: true
agent/tools/calendar.py:
from langchain_core.tools import tool
@tool
def check_team_availability(date: str) -> str:
"""Check team calendar for available meeting slots.
Args:
date: Date in YYYY-MM-DD format
Returns:
Available time slots for team meetings.
"""
# Implementation using workspace calendar API
return get_team_availability(date)
Best Practices¶
- Clear identity - Give each workspace a distinct personality and purpose
- Focused capabilities - Don't try to make one agent do everything
- Consistent voice - Maintain personality across all markdown files
- Appropriate permissions - Use
allowed_users/allowed_groupsto restrict access - Regular updates - Keep HEARTBEAT.md current with ongoing work
- Tool organization - Use descriptive names and comprehensive docstrings
- Cron hygiene - Disable unused cron jobs (
enabled: false) rather than deleting - Timezone awareness - Set workspace timezone for accurate scheduling and display
- Task management - Use TASKS.yaml for long-running work across conversations
- Archive review - Encourage agents to review conversation archives for long-term context
- Security - Never commit API keys or tokens; use
.envand environment variables
