Skip to content

Planning Capability Specification

Capability Identity

PropertyValue
EnumA2ECapability.PLANNING
String"planning"
Plugin TypeHermesPlanningPlugin (extends A2EPlugin)
Namespaceplanning/*
Message Count6

Overview

The planning capability provides a generic planning primitive. Plans contain tasks with configurable status columns. A kanban board is one concrete view — tasks grouped by their status column. The same task/status model supports any column-based workflow (waterfall phases, OKR trees, sprints).

Protocol Flow — Create Plan and Add Tasks

Message Types (6)

planning/plan/create — PlanCreateRequest

Agent → Host. Create a new plan with an optional column vocabulary.

FieldTypeRequiredDefaultDescription
typestrYes"planning/plan/create"Message type
idstrYesautoMessage UUID
versionstrYes"1.0"Protocol version
tsfloatYesautoTimestamp
namestrNo"default"Plan display name
columnslist[str]No[]Column vocabulary (empty = ["backlog", "todo", "in_progress", "done"])
descriptionstrNo""Plan description

PlanCreateResponse

Host → Agent.

FieldTypeRequiredDefaultDescription
typestrYes"planning/plan/create/resp"Message type
idstrYesautoMessage UUID
req_idstrNo""Echo of request ID
successboolYesFalseWhether the plan was created
plan_idstrYes""The new plan ID
columnslist[str]Yes[]The resolved column vocabulary

planning/plan/list — PlanListRequest

Agent → Host. List all plans.

FieldTypeRequiredDefaultDescription
typestrYes"planning/plan/list"Message type
idstrYesautoMessage UUID

PlanListResponse

Host → Agent.

FieldTypeRequiredDefaultDescription
typestrYes"planning/plan/list/resp"Message type
idstrYesautoMessage UUID
req_idstrNo""Echo of request ID
planslist[dict]Yes[]List of {plan_id, name, columns} dicts

planning/task/add — TaskAddRequest

Agent → Host. Add a task to a plan.

FieldTypeRequiredDefaultDescription
typestrYes"planning/task/add"Message type
idstrYesautoMessage UUID
plan_idstrYesParent plan ID
titlestrYesTask title
statusstrNo"backlog"Task status
descriptionstrNo""Task description
assigneestrNo""Assigned user/agent
depslist[str]No[]Task dependencies
metadatadictNo{}Arbitrary metadata

TaskAddResponse

Host → Agent.

FieldTypeRequiredDefaultDescription
typestrYes"planning/task/add/resp"Message type
idstrYesautoMessage UUID
req_idstrNo""Echo of request ID
successboolYesFalseWhether the task was added
task_idstrYes""The new task ID
statusstrYes""The assigned status

planning/task/update — TaskUpdateRequest

Agent → Host. Update a task's status, assignee, or dependencies.

FieldTypeRequiredDefaultDescription
typestrYes"planning/task/update"Message type
idstrYesautoMessage UUID
plan_idstrYesParent plan ID
task_idstrYesTask ID to update
statusstrNo""New status (empty = no change)
assigneestrNo""New assignee
depslist[str]No[]New dependency list

TaskUpdateResponse

Host → Agent.

FieldTypeRequiredDefaultDescription
typestrYes"planning/task/update/resp"Message type
idstrYesautoMessage UUID
req_idstrNo""Echo of request ID
successboolYesFalseWhether the update succeeded
task_idstrYes""The updated task ID

planning/task/list — TaskListRequest

Agent → Host. List tasks, optionally filtered by plan and/or status.

FieldTypeRequiredDefaultDescription
typestrYes"planning/task/list"Message type
idstrYesautoMessage UUID
plan_idstrNo""Filter by plan (empty = all plans)
statusstrNo""Filter by status (empty = all statuses)

TaskListResponse

Host → Agent.

FieldTypeRequiredDefaultDescription
typestrYes"planning/task/list/resp"Message type
idstrYesautoMessage UUID
req_idstrNo""Echo of request ID
taskslist[dict]Yes[]List of {task_id, title, status, assignee, plan_id} dicts

planning/plan/board — PlanBoardRequest

Agent → Host. Get the kanban-style board view (tasks grouped by status column).

FieldTypeRequiredDefaultDescription
typestrYes"planning/plan/board"Message type
idstrYesautoMessage UUID
plan_idstrNo""Filter by plan (empty = all plans, one board each)

PlanBoardResponse

Host → Agent.

FieldTypeRequiredDefaultDescription
typestrYes"planning/plan/board/resp"Message type
idstrYesautoMessage UUID
req_idstrNo""Echo of request ID
boardslist[dict]Yes[]Board views, each with plan_id, name, columns, tasks

Each board's tasks groups tasks by column: {"backlog": [...], "todo": [...], "in_progress": [...], "done": [...]}.

Error Codes

ErrorCondition
invalid_messageUnrecognized planning message type
runtime_errorSQLite or internal error

Plugin Contract

The HermesPlanningPlugin extends A2EPlugin directly (not through an SDK abstract base):

supported_messages()

Returns a dict mapping PlanningMessageType enum values to request model classes:

python
{
    PlanningMessageType.PLAN_CREATE: PlanCreateRequest,
    PlanningMessageType.PLAN_LIST: PlanListRequest,
    PlanningMessageType.TASK_ADD: TaskAddRequest,
    PlanningMessageType.TASK_UPDATE: TaskUpdateRequest,
    PlanningMessageType.TASK_LIST: TaskListRequest,
    PlanningMessageType.PLAN_BOARD: PlanBoardRequest,
}

handle(msg)

Dispatches by message type to one of six handler methods:

HandlerMessage TypeReturns
_create_planplanning/plan/createPlanCreateResponse
_list_plansplanning/plan/listPlanListResponse
_add_taskplanning/task/addTaskAddResponse
_update_taskplanning/task/updateTaskUpdateResponse
_list_tasksplanning/task/listTaskListResponse
_boardplanning/plan/boardPlanBoardResponse

Storage

  • SQLite database at config["ROOT"]/planning.db
  • Two tables: plans (plan_id, name, columns, description, created_at) and tasks (task_id, plan_id, title, status, description, assignee, deps, metadata, created_at)
  • Thread-safe via threading.RLock()

Config Example

yaml
plugins:
  - name: planning
    type: planning
    cls: a2e.caps.planning.plugin.HermesPlanningPlugin
    metadata:
      enabled: true
      priority: 0
      ROOT: "/tmp/a2e/planning"

Wire Example

json
// Agent → Host: Create a plan
{"type": "planning/plan/create", "id": "...", "name": "release", "columns": ["backlog", "todo", "in_progress", "done"], "description": "ship it"}

// Host → Agent: Plan created
{"type": "planning/plan/create/resp", "id": "...", "req_id": "...", "success": true, "plan_id": "abc123", "columns": ["backlog", "todo", "in_progress", "done"]}

// Agent → Host: Add a task
{"type": "planning/task/add", "id": "...", "plan_id": "abc123", "title": "write spec", "status": "todo"}

// Host → Agent: Task added
{"type": "planning/task/add/resp", "id": "...", "req_id": "...", "success": true, "task_id": "def456", "status": "todo"}

// Agent → Host: Get kanban board
{"type": "planning/plan/board", "id": "...", "plan_id": "abc123"}

// Host → Agent: Board view
{"type": "planning/plan/board/resp", "id": "...", "req_id": "...", "boards": [{"plan_id": "abc123", "name": "release", "columns": ["backlog", "todo", "in_progress", "done"], "tasks": {"backlog": [...], "todo": [{"task_id": "def456", "title": "write spec", "status": "todo", "assignee": ""}], "in_progress": [], "done": []}}]}

Security Considerations

  • The planning plugin stores data in a local SQLite file. In production, configure ROOT to a persistent volume.
  • No authentication or authorization — any connected agent can create/update/delete plans and tasks.
  • Task metadata is arbitrary JSON — validate content before displaying to users.
  • Dependency tracking (deps) is advisory only; no cycle detection is performed.

A2E Protocol v1.0 — Released under the MIT License.