Skip to main content
curl "http://localhost:8887/api/attempts?taskId=task_abc123&status=completed"
{
  "success": true,
  "data": [
    {
      "id": "attempt_abc123",
      "taskId": "task_xyz789",
      "llm": "claude",
      "status": "completed",
      "worktreePath": ".forge/worktrees/task-xyz-claude",
      "startedAt": "2024-01-15T10:30:00Z",
      "completedAt": "2024-01-15T10:45:00Z",
      "duration": 900000,
      "filesChanged": 8,
      "linesAdded": 245,
      "linesRemoved": 12,
      "cost": {
        "inputTokens": 15420,
        "outputTokens": 3890,
        "totalCost": 0.23
      }
    }
  ]
}

Overview

Attempts represent individual executions of tasks by AI agents. Each task can have multiple attempts with different agents or configurations. Base URL: http://localhost:8887/api/attempts

List Attempts

Get all attempts with filtering.
GET /api/attempts

Query Parameters

ParameterTypeDescription
taskIdstringFilter by task
llmstringFilter by AI agent
statusenumFilter by status
pageintegerPage number
limitintegerItems per page

Status Values

  • created - Queued, not started
  • running - Currently executing
  • completed - Finished successfully
  • failed - Execution failed
  • cancelled - Cancelled by user
curl "http://localhost:8887/api/attempts?taskId=task_abc123&status=completed"
{
  "success": true,
  "data": [
    {
      "id": "attempt_abc123",
      "taskId": "task_xyz789",
      "llm": "claude",
      "status": "completed",
      "worktreePath": ".forge/worktrees/task-xyz-claude",
      "startedAt": "2024-01-15T10:30:00Z",
      "completedAt": "2024-01-15T10:45:00Z",
      "duration": 900000,
      "filesChanged": 8,
      "linesAdded": 245,
      "linesRemoved": 12,
      "cost": {
        "inputTokens": 15420,
        "outputTokens": 3890,
        "totalCost": 0.23
      }
    }
  ]
}

Get Attempt

Retrieve detailed attempt information.
GET /api/attempts/:id

Example Response

{
  "success": true,
  "data": {
    "id": "attempt_abc123",
    "taskId": "task_xyz789",
    "llm": "claude",
    "model": "claude-3-5-sonnet-20241022",
    "status": "completed",
    "worktreePath": ".forge/worktrees/task-xyz-claude",
    "startedAt": "2024-01-15T10:30:00Z",
    "completedAt": "2024-01-15T10:45:00Z",
    "duration": 900000,
    "changes": {
      "filesChanged": 8,
      "filesCreated": 2,
      "filesModified": 6,
      "filesDeleted": 0,
      "linesAdded": 245,
      "linesRemoved": 12
    },
    "cost": {
      "inputTokens": 15420,
      "outputTokens": 3890,
      "totalCost": 0.23
    },
    "output": {
      "summary": "Successfully implemented JWT authentication",
      "changes": [
        "Created src/auth/jwt.ts for token generation",
        "Added login endpoint to src/api/auth.ts",
        "Added signup endpoint with validation",
        "Created authentication middleware",
        "Added comprehensive tests"
      ]
    }
  }
}

Create Attempt

Start a new attempt for a task.
POST /api/attempts

Request Body

{
  "taskId": "task_xyz789",
  "llm": "claude",
  "options": {
    "temperature": 0.7,
    "maxTokens": 4096,
    "timeout": 60000
  },
  "description": "Focus on security and edge cases"
}
curl -X POST http://localhost:8887/api/attempts \
  -H "Content-Type: application/json" \
  -d '{
    "taskId": "task_xyz789",
    "llm": "claude"
  }'
{
  "success": true,
  "data": {
    "id": "attempt_new123",
    "taskId": "task_xyz789",
    "llm": "claude",
    "status": "created",
    "createdAt": "2024-01-15T11:00:00Z"
  }
}

Start Attempt

Begin execution of a created attempt.
POST /api/attempts/:id/start
curl -X POST http://localhost:8887/api/attempts/attempt_new123/start
{
  "success": true,
  "data": {
    "id": "attempt_new123",
    "status": "running",
    "startedAt": "2024-01-15T11:00:00Z",
    "processId": "proc_abc123"
  }
}

Cancel Attempt

Stop a running attempt.
POST /api/attempts/:id/cancel
curl -X POST http://localhost:8887/api/attempts/attempt_abc123/cancel
{
  "success": true,
  "data": {
    "id": "attempt_abc123",
    "status": "cancelled",
    "cancelledAt": "2024-01-15T11:05:00Z"
  }
}

Delete Attempt

Remove an attempt and cleanup worktree.
DELETE /api/attempts/:id
This permanently deletes the attempt and removes the associated Git worktree.
curl -X DELETE http://localhost:8887/api/attempts/attempt_abc123
{
  "success": true,
  "data": {
    "deleted": true,
    "attemptId": "attempt_abc123"
  }
}

Get Attempt Logs

Retrieve execution logs for an attempt.
GET /api/attempts/:id/logs

Query Parameters

ParameterTypeDescription
followbooleanStream logs in real-time
levelenumFilter by log level
sincetimestampOnly logs after this time
curl "http://localhost:8887/api/attempts/attempt_abc123/logs?follow=true"
{"level":"info","message":"Starting attempt execution","timestamp":"2024-01-15T10:30:00Z"}
{"level":"info","message":"Creating git worktree","timestamp":"2024-01-15T10:30:01Z"}
{"level":"info","message":"Worktree created: .forge/worktrees/task-xyz-claude","timestamp":"2024-01-15T10:30:02Z"}
{"level":"info","message":"Initializing LLM: claude","timestamp":"2024-01-15T10:30:03Z"}
{"level":"info","message":"Generating code...","timestamp":"2024-01-15T10:30:05Z"}
{"level":"info","message":"Created file: src/auth/jwt.ts","timestamp":"2024-01-15T10:32:15Z"}

Get Attempt Diff

Get code changes made by the attempt.
GET /api/attempts/:id/diff

Query Parameters

ParameterTypeDescription
filestringSpecific file to diff
formatenumunified, split, json (default: unified)
curl "http://localhost:8887/api/attempts/attempt_abc123/diff?format=json"
{
  "success": true,
  "data": {
    "files": [
      {
        "path": "src/auth/jwt.ts",
        "status": "added",
        "additions": 67,
        "deletions": 0,
        "changes": [
          {
            "type": "add",
            "lineNumber": 1,
            "content": "import jwt from 'jsonwebtoken';"
          }
        ]
      },
      {
        "path": "src/api/auth.ts",
        "status": "modified",
        "additions": 132,
        "deletions": 13,
        "changes": [...]
      }
    ],
    "summary": {
      "filesChanged": 8,
      "additions": 245,
      "deletions": 12
    }
  }
}

Merge Attempt

Merge attempt changes into main branch.
POST /api/attempts/:id/merge

Request Body

{
  "message": "Add JWT authentication",
  "strategy": "squash",
  "cleanup": true
}

Merge Strategies

  • ff - Fast-forward merge (default)
  • no-ff - Create merge commit
  • squash - Squash commits into one
curl -X POST http://localhost:8887/api/attempts/attempt_abc123/merge \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Add JWT authentication (Claude implementation)",
    "strategy": "squash",
    "cleanup": true
  }'
{
  "success": true,
  "data": {
    "attemptId": "attempt_abc123",
    "commitSha": "abc123def456",
    "merged": true,
    "mergedAt": "2024-01-15T11:10:00Z",
    "cleanup": true
  }
}

Compare Attempts

Compare two attempts side-by-side.
POST /api/attempts/compare

Request Body

{
  "attemptIds": ["attempt_1", "attempt_2"]
}

Example Response

{
  "success": true,
  "data": {
    "attempts": [
      {
        "id": "attempt_1",
        "llm": "claude",
        "duration": 900000,
        "cost": 0.23,
        "filesChanged": 8,
        "linesAdded": 245
      },
      {
        "id": "attempt_2",
        "llm": "gemini",
        "duration": 450000,
        "cost": 0.00,
        "filesChanged": 6,
        "linesAdded": 189
      }
    ],
    "comparison": {
      "fasterAttempt": "attempt_2",
      "cheaperAttempt": "attempt_2",
      "moreCompleteAttempt": "attempt_1"
    }
  }
}

Get Commit Info

Get commit information for a task attempt.
GET /api/task-attempts/:id/commit-info

Example Response

{
  "success": true,
  "data": {
    "commitId": "abc123def456",
    "message": "Add user authentication (automagik-forge a1b2)",
    "author": "Claude AI <ai@automagik.ai>",
    "timestamp": "2024-01-15T10:45:00Z",
    "filesChanged": 8,
    "insertions": 245,
    "deletions": 12
  }
}

Compare to Head

Compare task attempt branch to HEAD of target branch.
GET /api/task-attempts/:id/compare-to-head

Example Response

{
  "success": true,
  "data": {
    "diff": "diff --git a/src/auth.ts...",
    "filesChanged": 8,
    "ahead": 3,
    "behind": 0,
    "conflicts": []
  }
}

Merge Attempt

Merge task attempt into target branch.
POST /api/task-attempts/:id/merge

Request Body

{
  "strategy": "squash",
  "message": "Add authentication system",
  "cleanup": true
}

Parameters

ParameterTypeDefaultDescription
strategyenumsquashMerge strategy: squash, merge, rebase
messagestringautoCustom commit message
cleanupbooleantrueDelete worktree after merge

Example Response

{
  "success": true,
  "data": {
    "commitId": "abc123def456",
    "mergedAt": "2024-01-15T11:00:00Z",
    "branch": "main",
    "filesChanged": 8
  }
}

Push Branch

Push task attempt branch to remote.
POST /api/task-attempts/:id/push

Request Body

{
  "remote": "origin",
  "force": false
}

Example Response

{
  "success": true,
  "data": {
    "remote": "origin",
    "branch": "forge/task-abc123-attempt-1",
    "pushedAt": "2024-01-15T10:50:00Z"
  }
}

Create GitHub PR

Create a pull request from task attempt branch.
POST /api/task-attempts/:id/create-pr

Request Body

{
  "title": "Add user authentication",
  "body": "Implements JWT-based authentication with refresh tokens",
  "baseBranch": "main",
  "draft": false
}

Example Response

{
  "success": true,
  "data": {
    "prNumber": 42,
    "url": "https://github.com/user/repo/pull/42",
    "createdAt": "2024-01-15T10:55:00Z"
  }
}

Attach Existing PR

Attach an existing GitHub PR to this attempt.
POST /api/task-attempts/:id/attach-pr

Request Body

{
  "prNumber": 42,
  "repository": "user/repo"
}

Example Response

{
  "success": true,
  "data": {
    "prNumber": 42,
    "url": "https://github.com/user/repo/pull/42",
    "status": "open"
  }
}

Open in Editor

Open task attempt worktree in IDE/editor.
POST /api/task-attempts/:id/open-in-editor

Request Body

{
  "editor": "vscode"
}

Supported Editors

  • vscode - Visual Studio Code
  • cursor - Cursor IDE
  • idea - IntelliJ IDEA
  • sublime - Sublime Text

Example Response

{
  "success": true,
  "data": {
    "editor": "vscode",
    "worktreePath": "/path/to/.forge/worktrees/task-abc123",
    "opened": true
  }
}

Get Branch Status

Get git status of task attempt branch.
GET /api/task-attempts/:id/branch-status

Example Response

{
  "success": true,
  "data": {
    "branch": "forge/task-abc123-attempt-1",
    "baseBranch": "main",
    "ahead": 3,
    "behind": 0,
    "conflicted": false,
    "modifiedFiles": [],
    "untrackedFiles": [],
    "status": "clean"
  }
}

Change Target Branch

Change the base branch for this attempt.
POST /api/task-attempts/:id/change-target-branch

Request Body

{
  "newBaseBranch": "develop"
}

Example Response

{
  "success": true,
  "data": {
    "previousBase": "main",
    "newBase": "develop",
    "conflicts": []
  }
}

Rebase Attempt

Rebase task attempt onto latest base branch.
POST /api/task-attempts/:id/rebase

Request Body

{
  "interactive": false
}

Example Response

{
  "success": true,
  "data": {
    "status": "success",
    "conflicts": [],
    "commitsReplayed": 3
  }
}
Conflict Response:
{
  "success": false,
  "data": {
    "status": "conflict",
    "conflicts": [
      "src/auth.ts",
      "src/users.ts"
    ]
  }
}

Abort Conflicts

Abort merge/rebase conflicts and return to clean state.
POST /api/task-attempts/:id/abort-conflicts

Example Response

{
  "success": true,
  "data": {
    "status": "clean",
    "abortedOperation": "rebase"
  }
}

Delete File

Delete a file from task attempt worktree.
DELETE /api/task-attempts/:id/files/:path

Example

curl -X DELETE \
  http://localhost:8887/api/task-attempts/attempt_123/files/src/old-file.ts

Example Response

{
  "success": true,
  "data": {
    "path": "src/old-file.ts",
    "deleted": true
  }
}

Start Dev Server

Start development server in task attempt worktree.
POST /api/task-attempts/:id/start-dev-server

Request Body

{
  "script": "dev",
  "port": 3000
}

Example Response

{
  "success": true,
  "data": {
    "processId": "process_abc123",
    "port": 3000,
    "url": "http://localhost:3000",
    "status": "running"
  }
}

Get Child Tasks

Get tasks created from this attempt (subtasks).
GET /api/task-attempts/:id/children

Example Response

{
  "success": true,
  "data": [
    {
      "id": "task_child1",
      "title": "Add unit tests for auth",
      "status": "todo",
      "createdAt": "2024-01-15T11:00:00Z"
    }
  ]
}

Replace Process

Replace the running execution process with a new one.
POST /api/task-attempts/:id/replace-process

Request Body

{
  "executorProfileId": {
    "executor": "CLAUDE_CODE",
    "variant": null
  },
  "prompt": "Continue with different approach"
}

Example Response

{
  "success": true,
  "data": {
    "oldProcessId": "process_123",
    "newProcessId": "process_456",
    "status": "running"
  }
}

SDK Examples

JavaScript/TypeScript

import { ForgeClient } from '@automagik/forge-sdk';

const forge = new ForgeClient();

// List attempts
const attempts = await forge.attempts.list({
  taskId: 'task_xyz789',
  status: 'completed'
});

// Create and start attempt
const attempt = await forge.attempts.create({
  taskId: 'task_xyz789',
  llm: 'claude'
});

await forge.attempts.start(attempt.id);

// Get logs (streaming)
const logs = await forge.attempts.logs(attempt.id, {
  follow: true
});

for await (const log of logs) {
  console.log(log.message);
}

// Get diff
const diff = await forge.attempts.diff(attempt.id);

// Merge when ready
await forge.attempts.merge(attempt.id, {
  message: 'Add authentication',
  strategy: 'squash',
  cleanup: true
});

// Compare attempts
const comparison = await forge.attempts.compare([
  'attempt_1',
  'attempt_2'
]);

Python

from automagik_forge import ForgeClient

forge = ForgeClient()

# Create and start attempt
attempt = forge.attempts.create(
    task_id='task_xyz789',
    llm='claude'
)

forge.attempts.start(attempt.id)

# Stream logs
for log in forge.attempts.logs(attempt.id, follow=True):
    print(log.message)

# Get diff
diff = forge.attempts.diff(attempt.id)

# Merge
forge.attempts.merge(
    attempt.id,
    message='Add authentication',
    strategy='squash',
    cleanup=True
)

WebSocket Events

Subscribe to real-time attempt updates:
const ws = new WebSocket('ws://localhost:8887/ws');

ws.send(JSON.stringify({
  type: 'subscribe',
  channel: 'attempts',
  attemptId: 'attempt_abc123'
}));

ws.onmessage = (event) => {
  const update = JSON.parse(event.data);
  // { type: 'attempt.status_changed', attemptId: '...', status: 'running' }
};

Next Steps