Skip to content

Agent Actions Reference

This document describes the action schema for Loom agents. Agents use these actions to interact with the codebase, run commands, manage beads, and execute tests.

Action Envelope Format

All agent responses must be valid JSON matching this schema:

{
  "actions": [
    {
      "type": "action_name",
      // action-specific fields
    }
  ],
  "notes": "Optional notes about the actions"
}

Available Actions

File Operations

read_file

Read the contents of a file.

{
  "type": "read_file",
  "path": "src/main.go"
}

Fields: - path (required): Path to file relative to project root

Returns: - path: Absolute file path - content: File contents - size: File size in bytes

write_file

Write content to a file (creates or overwrites).

{
  "type": "write_file",
  "path": "src/config.json",
  "content": "{\"key\": \"value\"}"
}

Fields: - path (required): Path to file - content (required): File contents to write

Returns: - path: Absolute file path - bytes_written: Number of bytes written

read_code

Alias for read_file (legacy, prefer read_file).

edit_code

Apply a unified diff patch to files.

{
  "type": "edit_code",
  "path": "src/main.go",
  "patch": "--- a/src/main.go\n+++ b/src/main.go\n@@ -10,7 +10,7 @@\n-\told code\n+\tnew code"
}

Fields: - path (required): Path to file being patched - patch (required): Unified diff in git format

Returns: - output: Patch application output

apply_patch

Apply a multi-file unified diff patch.

{
  "type": "apply_patch",
  "patch": "diff --git a/file1.go b/file1.go\n..."
}

Fields: - patch (required): Multi-file unified diff

Returns: - output: Patch application results

read_tree

List directory contents recursively.

{
  "type": "read_tree",
  "path": "src",
  "max_depth": 3,
  "limit": 100
}

Fields: - path (optional): Directory path (default: ".") - max_depth (optional): Maximum recursion depth - limit (optional): Maximum entries to return

Returns: - entries: Array of file/directory entries

search_text

Search for text in files using grep.

{
  "type": "search_text",
  "path": "src",
  "query": "TODO",
  "limit": 50
}

Fields: - path (optional): Directory to search (default: ".") - query (required): Search pattern - limit (optional): Maximum matches to return

Returns: - matches: Array of matching lines with file/line info

Command Execution

run_command

Execute a shell command in the project directory.

{
  "type": "run_command",
  "command": "npm install",
  "working_dir": "frontend"
}

Fields: - command (required): Shell command to execute - working_dir (optional): Working directory for command

Returns: - command_id: Execution ID for tracking - exit_code: Command exit code

Security: Commands are executed in a sandboxed environment with resource limits.

run_tests

Execute project tests and return structured results.

{
  "type": "run_tests",
  "test_pattern": "TestCalculator",
  "framework": "go",
  "timeout_seconds": 300
}

Fields: - test_pattern (optional): Pattern to filter tests (e.g., "TestFoo*", "test_bar") - framework (optional): Test framework to use ("go", "jest", "pytest", "npm") - timeout_seconds (optional): Maximum execution time in seconds

Returns:

{
  "framework": "go",
  "success": false,
  "exit_code": 1,
  "timed_out": false,
  "duration": "1.234s",
  "summary": {
    "total": 10,
    "passed": 8,
    "failed": 2,
    "skipped": 0
  },
  "tests": [
    {
      "name": "TestCalculate",
      "package": "github.com/user/pkg",
      "status": "fail",
      "duration": "0.123s",
      "error": "Expected 100, got 99",
      "stack_trace": "..."
    }
  ],
  "raw_output": "full test output..."
}

Framework Auto-Detection:

If framework is not specified, the system auto-detects based on:

  • Go: Presence of go.mod or *_test.go files
  • Jest: package.json with jest dependency
  • npm: Generic package.json without specific framework
  • pytest: pytest.ini, pyproject.toml, or test_*.py files

Examples:

Run all tests with auto-detection:

{
  "type": "run_tests"
}

Run specific Go tests:

{
  "type": "run_tests",
  "test_pattern": "TestDatabase",
  "framework": "go"
}

Run Jest tests with custom timeout:

{
  "type": "run_tests",
  "test_pattern": "should handle errors",
  "framework": "jest",
  "timeout_seconds": 600
}

Run pytest with pattern:

{
  "type": "run_tests",
  "test_pattern": "test_api",
  "framework": "pytest"
}

Test-Fix-Retest Pattern:

{
  "actions": [
    {"type": "run_tests"},
    {"type": "read_file", "path": "src/calculator.go"},
    {"type": "edit_code", "path": "src/calculator.go", "patch": "..."},
    {"type": "run_tests", "test_pattern": "TestCalculate"}
  ],
  "notes": "Fixed off-by-one error in Calculate function"
}

run_linter

Execute linters to check code quality and style.

{
  "type": "run_linter",
  "files": ["internal/*.go", "pkg/*.go"],
  "framework": "golangci-lint",
  "timeout_seconds": 300
}

Fields: - files (optional): Specific files/patterns to lint (default: all files) - framework (optional): Linter framework ("golangci-lint", "eslint", "pylint") - timeout_seconds (optional): Maximum execution time in seconds

Returns:

{
  "framework": "golangci-lint",
  "success": false,
  "exit_code": 1,
  "duration": "2.345s",
  "violation_count": 2,
  "violations": [
    {
      "file": "internal/foo.go",
      "line": 10,
      "column": 2,
      "rule": "unused",
      "severity": "error",
      "message": "unused variable 'x'",
      "linter": "unused"
    }
  ],
  "raw_output": "full linter output..."
}

Framework Auto-Detection:

If framework is not specified, the system auto-detects based on:

  • golangci-lint: Presence of go.mod or *.go files
  • eslint: .eslintrc.js, .eslintrc.json, or eslint in package.json
  • pylint: .pylintrc or *.py files

Examples:

Run all linters with auto-detection:

{
  "type": "run_linter"
}

Run golangci-lint on specific files:

{
  "type": "run_linter",
  "files": ["internal/api/*.go"],
  "framework": "golangci-lint"
}

Run eslint with custom timeout:

{
  "type": "run_linter",
  "framework": "eslint",
  "timeout_seconds": 600
}

Lint-Fix-Relint Pattern:

{
  "actions": [
    {"type": "run_linter"},
    {"type": "read_file", "path": "internal/foo.go"},
    {"type": "edit_code", "path": "internal/foo.go", "patch": "..."},
    {"type": "run_linter", "files": ["internal/foo.go"]}
  ],
  "notes": "Fixed unused variable and formatting issues"
}

build_project

Execute project builds to verify compilation and catch build errors.

{
  "type": "build_project",
  "build_target": "myapp",
  "build_command": "go build -o myapp ./cmd/app",
  "framework": "go",
  "timeout_seconds": 300
}

Fields: - build_target (optional): Build output target (e.g., binary name) - build_command (optional): Custom build command (overrides framework default) - framework (optional): Build framework ("go", "npm", "make", "cargo", "maven", "gradle") - timeout_seconds (optional): Maximum execution time in seconds

Returns:

{
  "framework": "go",
  "success": false,
  "exit_code": 1,
  "duration": "3.456s",
  "error_count": 2,
  "errors": [
    {
      "file": "internal/foo.go",
      "line": 10,
      "column": 2,
      "message": "undefined: someFunc",
      "type": "error"
    }
  ],
  "warnings": [],
  "raw_output": "full build output...",
  "timed_out": false,
  "error": ""
}

Framework Auto-Detection:

If framework is not specified, the system auto-detects based on:

  • go: Presence of go.mod or *.go files
  • npm: package.json file
  • make: Makefile or makefile
  • cargo: Cargo.toml file (Rust)
  • maven: pom.xml file (Java)
  • gradle: build.gradle or build.gradle.kts files (Java)

Examples:

Run build with auto-detection:

{
  "type": "build_project"
}

Build Go project with custom target:

{
  "type": "build_project",
  "build_target": "myapp",
  "framework": "go"
}

Build npm project:

{
  "type": "build_project",
  "framework": "npm"
}

Build with custom command:

{
  "type": "build_project",
  "build_command": "go build -v -tags production ./...",
  "timeout_seconds": 600
}

Build-Fix-Rebuild Pattern:

{
  "actions": [
    {"type": "build_project"},
    {"type": "read_file", "path": "internal/parser.go"},
    {"type": "edit_code", "path": "internal/parser.go", "patch": "..."},
    {"type": "build_project"}
  ],
  "notes": "Fixed compilation error in parser"
}

Complete Quality Check Pattern:

{
  "actions": [
    {"type": "build_project"},
    {"type": "run_tests"},
    {"type": "run_linter"}
  ],
  "notes": "Comprehensive verification: build, test, and lint"
}

Git Operations

git_status

Get git status for the project.

{
  "type": "git_status"
}

Returns: - output: Git status output

git_diff

Get git diff for the project.

{
  "type": "git_diff"
}

Returns: - output: Git diff output

Bead Management

create_bead

Create a new bead (issue/task).

{
  "type": "create_bead",
  "bead": {
    "title": "Fix authentication bug",
    "description": "Users cannot login after password reset",
    "project_id": "proj-123",
    "priority": 1,
    "type": "bug",
    "tags": ["security", "urgent"]
  }
}

Fields: - bead (required): Bead payload object - title (required): Bead title - project_id (required): Project identifier - description (optional): Detailed description - priority (optional): Priority level (0-4, where 0=critical, 4=backlog) - type (optional): Bead type ("task", "bug", "feature", "epic") - tags (optional): Array of tags

Returns: - bead_id: Created bead identifier

close_bead

Mark a bead as complete.

{
  "type": "close_bead",
  "bead_id": "bead-abc-123",
  "reason": "Fixed authentication bug and added tests"
}

Fields: - bead_id (required): Bead identifier - reason (optional): Closure reason/notes

Returns: - bead_id: Closed bead identifier

escalate_ceo

Escalate a bead to CEO for decision.

{
  "type": "escalate_ceo",
  "bead_id": "bead-abc-123",
  "reason": "Need architectural decision on database choice",
  "returned_to": "agent-456"
}

Fields: - bead_id (required): Bead to escalate - reason (optional): Escalation reason - returned_to (optional): Agent to return decision to

Returns: - decision_id: Created decision bead identifier

approve_bead

Approve a bead in a workflow.

{
  "type": "approve_bead",
  "bead_id": "bead-abc-123",
  "reason": "Code review passed, tests are comprehensive"
}

Fields: - bead_id (required): Bead to approve - reason (optional): Approval reason

Returns: - bead_id: Approved bead identifier

reject_bead

Reject a bead in a workflow.

{
  "type": "reject_bead",
  "bead_id": "bead-abc-123",
  "reason": "Missing error handling in new code"
}

Fields: - bead_id (required): Bead to reject - reason (required): Rejection reason

Returns: - bead_id: Rejected bead identifier - reason: Rejection reason

Communication

ask_followup

Ask the user a follow-up question.

{
  "type": "ask_followup",
  "question": "Should I use PostgreSQL or MySQL for the database?"
}

Fields: - question (required): Question to ask

Note: This creates a bead with the question for the user to answer.

send_agent_message

Send a message to another agent for collaboration, delegation, or notification.

{
  "type": "send_agent_message",
  "to_agent_id": "agent-qa-engineer-1",
  "message_type": "question",
  "message_subject": "Test coverage check",
  "message_body": "Can you verify test coverage for the auth module is above 80%?",
  "message_payload": {
    "module": "auth",
    "files": ["src/auth.go", "src/auth_test.go"]
  }
}

Fields: - to_agent_id (optional): Target agent ID (use this OR to_agent_role) - to_agent_role (optional): Target agent role/persona (e.g., "qa-engineer", "code-reviewer") - message_type (required): One of: "question", "delegation", "notification" - question: Ask another agent for information - delegation: Request another agent to perform a task - notification: Inform another agent of an event - message_subject (optional): Brief subject line - message_body (optional): Detailed message content - message_payload (optional): Additional context or data

Returns: - message_id: Unique message identifier - to_agent_id: Resolved target agent ID - message_type: Message type sent - message_subject: Message subject

Examples:

Delegate task to QA agent:

{
  "type": "send_agent_message",
  "to_agent_role": "qa-engineer",
  "message_type": "delegation",
  "message_subject": "Run integration tests",
  "message_body": "Please run full integration test suite for the authentication module",
  "message_payload": {
    "test_pattern": "TestAuth*",
    "bead_id": "bead-abc-123"
  }
}

Ask code reviewer for feedback:

{
  "type": "send_agent_message",
  "to_agent_role": "code-reviewer",
  "message_type": "question",
  "message_subject": "API design review",
  "message_body": "Does this API design follow our best practices?"
}

Notify project manager of completion:

{
  "type": "send_agent_message",
  "to_agent_id": "agent-pm-1",
  "message_type": "notification",
  "message_subject": "Feature complete",
  "message_body": "Authentication feature is complete and all tests pass"
}

delegate_task

Create a child bead and delegate it to another agent for task decomposition.

{
  "type": "delegate_task",
  "delegate_to_role": "qa-engineer",
  "task_title": "Run integration tests for auth module",
  "task_description": "Execute full integration test suite for the authentication module, including edge cases and error handling",
  "task_priority": 2,
  "parent_bead_id": "bead-abc-123"
}

Fields: - delegate_to_role (required): Role/persona to delegate task to - task_title (required): Title for the delegated task (child bead) - task_description (optional): Detailed description for the child bead - task_priority (optional): Priority 0-4 (P0=critical, P2=medium, P4=backlog). Defaults to 0 if not specified. - parent_bead_id (optional): Parent bead ID. If not provided, uses the current bead as parent.

Returns: - child_bead_id: ID of the newly created child bead - parent_bead_id: ID of the parent bead - delegate_to_role: Role the task was delegated to - task_title: Title of the delegated task - task_priority: Priority assigned to the task

Examples:

Delegate testing to QA agent:

{
  "type": "delegate_task",
  "delegate_to_role": "qa-engineer",
  "task_title": "Test authentication flow",
  "task_description": "Verify all authentication scenarios work correctly",
  "task_priority": 1
}

Delegate code review:

{
  "type": "delegate_task",
  "delegate_to_role": "code-reviewer",
  "task_title": "Review authentication PR",
  "task_description": "Review PR #456 for security and code quality",
  "task_priority": 2,
  "parent_bead_id": "bead-feature-auth"
}

Delegate performance optimization:

{
  "type": "delegate_task",
  "delegate_to_role": "performance-engineer",
  "task_title": "Optimize database queries",
  "task_description": "Profile and optimize slow database queries in the auth module",
  "task_priority": 3
}

Use Cases:

  • Task Decomposition: Break down complex tasks into subtasks for specialized agents
  • Parallel Work: Delegate independent subtasks to multiple agents simultaneously
  • Skill Matching: Assign work to agents with specific expertise (QA, review, optimization)
  • Dependency Tracking: Parent bead tracks completion of all child beads

Action Results

All actions return a result with this structure:

{
  "action_type": "run_tests",
  "status": "executed",
  "message": "tests executed",
  "metadata": {
    // action-specific result data
  }
}

Status Values: - executed: Action completed successfully - error: Action failed with error

Multi-Action Patterns

Sequential Actions

Execute multiple actions in order:

{
  "actions": [
    {"type": "read_file", "path": "src/main.go"},
    {"type": "write_file", "path": "src/config.json", "content": "{}"},
    {"type": "run_command", "command": "go build"}
  ]
}

Test-Driven Development

{
  "actions": [
    {"type": "write_file", "path": "src/calculator_test.go", "content": "..."},
    {"type": "run_tests", "test_pattern": "TestAdd"},
    {"type": "write_file", "path": "src/calculator.go", "content": "..."},
    {"type": "run_tests", "test_pattern": "TestAdd"}
  ],
  "notes": "TDD: Write failing test, implement code, verify test passes"
}

Debug and Fix

{
  "actions": [
    {"type": "run_tests"},
    {"type": "read_file", "path": "src/auth.go"},
    {"type": "edit_code", "path": "src/auth.go", "patch": "..."},
    {"type": "run_tests", "test_pattern": "TestAuth"}
  ],
  "notes": "Fixed nil pointer dereference in authentication handler"
}

Comprehensive Code Change

{
  "actions": [
    {"type": "git_status"},
    {"type": "search_text", "query": "TODO", "path": "src"},
    {"type": "write_file", "path": "src/feature.go", "content": "..."},
    {"type": "run_tests"},
    {"type": "git_status"}
  ],
  "notes": "Implemented new feature with tests"
}

Error Handling

If an action fails, the result will have status: "error":

{
  "action_type": "run_tests",
  "status": "error",
  "message": "test runner not configured"
}

Common Errors:

  • "file not found": File doesn't exist
  • "patch failed": Patch couldn't be applied
  • "test runner not configured": Test execution unavailable
  • "command execution failed": Shell command returned non-zero exit
  • "bead creator not configured": Bead operations unavailable

Error Recovery:

When tests fail, the agent should: 1. Analyze the test failure output 2. Read relevant source files 3. Make targeted fixes 4. Re-run tests to verify

Example:

{
  "actions": [
    {"type": "run_tests"},
    // Test fails, agent analyzes output
    {"type": "read_file", "path": "src/parser.go"},
    {"type": "edit_code", "path": "src/parser.go", "patch": "..."},
    {"type": "run_tests", "test_pattern": "TestParser"}
  ],
  "notes": "Fixed parser to handle edge case"
}

Best Practices

1. Always Run Tests After Code Changes

{
  "actions": [
    {"type": "write_file", "path": "src/feature.go", "content": "..."},
    {"type": "run_tests"}
  ]
}

2. Use Specific Test Patterns When Debugging

Instead of:

{"type": "run_tests"}

Use:

{"type": "run_tests", "test_pattern": "TestSpecificFunction"}

3. Include Meaningful Notes

{
  "actions": [...],
  "notes": "Fixed off-by-one error in pagination logic (lines 45-47)"
}

4. Check Git Status Before Major Changes

{
  "actions": [
    {"type": "git_status"},
    {"type": "git_diff"},
    // ... make changes ...
  ]
}

5. Read Before Writing

{
  "actions": [
    {"type": "read_file", "path": "src/config.go"},
    {"type": "edit_code", "path": "src/config.go", "patch": "..."}
  ]
}

6. Use Appropriate Timeouts for Tests

{
  "type": "run_tests",
  "test_pattern": "TestIntegration",
  "timeout_seconds": 600
}

Validation Rules

The action schema validates:

  1. Required Fields: Each action type has required fields that must be present
  2. Unknown Fields: Strict decoding rejects unknown fields
  3. Action Array: At least one action must be present
  4. Type Values: Action type must be one of the defined constants

Implementation

The action schema is implemented in:

  • internal/actions/schema.go - Action types and validation
  • internal/actions/router.go - Action execution routing
  • internal/actions/testrunner_adapter.go - Test execution integration

Contributing

When adding new actions:

  1. Add constant to schema.go
  2. Add fields to Action struct if needed
  3. Add validation in validateAction()
  4. Add router case in executeAction()
  5. Write unit and integration tests
  6. Update this documentation

License

See LICENSE for details.