Skip to content

Agents

An Agent is a configured Claude Code instance with its own identity, workspace, permissions, and schedules. Think of it as a specialized team member that operates autonomously on your codebase.

Agent composition diagram showing identity, workspace, schedules, permissions, and optional components like work sources, chat, MCP, hooks, and sessions

Each agent operates independently with:

  • Identity: CLAUDE.md instructions, knowledge files, personality
  • Workspace: The working directory (repo clone) the agent operates in
  • Permissions: Exactly which tools the agent can use
  • Schedules: When and how to invoke (multiple allowed per agent)

Every herdctl agent has a workspace directory. This creates two natural categories depending on how that workspace is used.

Standalone agents have their own dedicated workspace for storing data. A price checker keeps price history in its folder. A hurricane tracker stores weather data. These agents do not need an existing codebase — they create their own working environment from scratch and use their workspace primarily for data persistence.

Project-embedded agents run inside an existing Claude Code project — one that already has a CLAUDE.md, local skills, sub-agents, and project-specific configuration. When you point a herdctl agent at an existing project directory, it operates exactly as if you ran claude in that directory. Your instructions are honored, your slash commands work, and your MCP servers are available. This means you can add autonomous capabilities (scheduled jobs, chat interfaces, webhook triggers) to any existing Claude Code project without changing how that project is set up.

PropertyRequiredDescription
nameYesUnique identifier for the agent within your fleet
descriptionNoHuman-readable explanation of the agent’s purpose
workspaceYesDirectory name for the agent’s working copy
repoYesGit repository to clone (e.g., owner/repo)
identityNoAgent-specific CLAUDE.md and knowledge files
schedulesYesOne or more triggers defining when the agent runs
work_sourceNoWhere the agent gets tasks from (e.g., GitHub Issues)
permissionsNoTool access and file restrictions
sessionNoSession persistence and timeout settings

Here’s a complete example of an agent that implements features and fixes bugs:

agents/bragdoc-coder.yaml
name: bragdoc-coder
description: "Implements features and fixes bugs in Bragdoc"
# Workspace (the repo this agent works in)
workspace: bragdoc-ai
repo: edspencer/bragdoc-ai
# Agent identity
identity:
claude_md: inherit # Use repo's CLAUDE.md
knowledge_dir: .claude/knowledge/
journal: journal.md # Persistent memory
# Work source configuration
work_source:
type: github
filter:
labels:
any: ["ready", "bug", "feature"]
exclude_labels: ["blocked", "needs-design"]
claim:
add_label: "in-progress"
remove_label: "ready"
complete:
remove_label: "in-progress"
close_issue: true
comment: "Completed: {{summary}}"
# Schedule for checking issues
schedules:
- name: issue-check
trigger:
type: interval
every: 5m
prompt: |
Check for ready issues in the repository.
Pick the oldest one and implement it.
Update journal.md with your progress.
# Session management
session:
mode: fresh_per_job # New session per job

Every agent has a unique identity defined by:

A unique identifier for the agent within your fleet. Use descriptive names that indicate the agent’s purpose:

  • bragdoc-coder - Implements features
  • bragdoc-marketer - Handles marketing tasks
  • project-support - Answers user questions

A human-readable description of what the agent does. This appears in the dashboard and helps team members understand each agent’s role.

Agent-specific instructions that define behavior, conventions, and context. You can:

  • Inherit the repo’s existing CLAUDE.md
  • Specify a custom file (e.g., .claude/marketer-CLAUDE.md)
  • Extend with additional knowledge files
identity:
claude_md: .claude/marketer-CLAUDE.md # Custom identity
knowledge_dir: .claude/knowledge/ # Additional context

Multiple agents can share the same workspace (repo clone). For example:

  • bragdoc-coder - Implements features in bragdoc-ai
  • bragdoc-marketer - Handles marketing in bragdoc-ai
  • bragdoc-support - Answers questions about bragdoc-ai

Each has different schedules, prompts, and potentially different identity files, but they all work on the same codebase.

  1. Created: Agent configuration loaded from YAML
  2. Initialized: Workspace cloned and prepared
  3. Idle: Waiting for next trigger
  4. Running: Executing a scheduled task (creates a Job)
  5. Completed: Task finished, returns to idle
  6. Stopped: Agent manually stopped

Implements features and fixes bugs from issue trackers:

name: project-coder
description: "Implements features from GitHub Issues"
workspace: my-project
repo: owner/my-project
work_source:
type: github
filter:
labels:
any: ["ready"]
schedules:
- name: issue-check
trigger:
type: interval
every: 5m
prompt: "Check for ready issues and implement the oldest one."

Monitors channels and generates reports:

name: project-marketer
description: "Monitors social media and generates analytics"
workspace: my-project
repo: owner/my-project
schedules:
- name: hourly-scan
trigger:
type: cron
cron: "0 * * * *"
prompt: "Scan social media for product mentions."
- name: daily-report
trigger:
type: cron
cron: "0 9 * * *"
prompt: "Generate daily analytics report."

Responds to chat messages. Chat-enabled agents appear as distinct “colleagues” in your messaging platform.

Discord — each agent has its own Discord bot:

name: project-support
description: "Answers user questions in Discord"
workspace: my-project
repo: owner/my-project
chat:
discord:
bot_token_env: SUPPORT_DISCORD_TOKEN # This agent's own bot
guilds:
- id: "guild-id-here"
channels:
- id: "123456789"
mode: mention # Responds when @mentioned
dm:
enabled: true
mode: auto
session:
mode: per_channel # Separate context per channel

Slack — agents share one bot, with different channels routing to different agents:

name: project-support
description: "Answers user questions in Slack"
workspace: my-project
repo: owner/my-project
chat:
slack:
bot_token_env: SLACK_BOT_TOKEN
app_token_env: SLACK_APP_TOKEN
channels:
- id: "C0123456789"
mode: mention # Responds when @mentioned
session:
mode: per_channel # Separate context per channel

For the complete schema and all available options, see: