---
title: Agent & Automation Mode
description: >-
  Structured JSON output, CI/CD automation patterns, and machine-readable CLI
  interfaces.
tags:
  - agent-mode
  - ci-cd
  - automation
  - json
  - scripting
---

Agent mode turns the ivybloom CLI into a machine-readable interface, wrapping every response in a structured JSON envelope for reliable parsing. Reach for it when you're scripting the CLI or wiring it into CI/CD pipelines, where you need predictable output, exit codes, and error codes rather than human-formatted tables. It runs against the same backend and job history as interactive use, so automated runs share state with your terminal and web work. For the full command set, see the [CLI overview](/docs/cli).

  intermediate

## Agent & Automation Mode

Structured JSON output, CI/CD automation patterns, and machine-readable CLI interfaces.

---

## Overview

The ivybloom CLI provides three automation modes for machine consumption:

| Mode | Flag | Description |
|------|------|-------------|
| **Agent** | `--agent` | Full JSON envelope with metadata |
| **Script** | `--script` / `-p` / `--simple` | Stripped output, no TUI elements |
| **JSON** | `--json` | Pretty JSON without envelope wrapper |

---

## Agent Mode

Agent mode wraps every CLI response in a standardized JSON envelope for reliable parsing.

```bash
ivybloom jobs list --agent
```

### Success Envelope

```json
{
  "success": true,
  "data": {
    "jobs": [
      {"id": "job_abc123", "tool": "esmfold", "status": "completed"},
      {"id": "job_def456", "tool": "admet", "status": "running"}
    ],
    "total": 2
  },
  "meta": {
    "envelope_version": "1.2.0",
    "timestamp": "2026-03-08T12:00:00Z",
    "cli_version": "0.8.10",
    "duration_ms": 1234,
    "command": "jobs list",
    "exit_code": 0
  }
}
```

`meta` also carries `request_id` and `trace_id` when they are set.

### Error Envelope

```json
{
  "success": false,
  "error": {
    "code": "ERR_INVALID_INPUT",
    "message": "Invalid protein sequence",
    "hint": "Check the sequence for non-amino-acid characters",
    "http_status": 400,
    "server_code": "INVALID_SEQUENCE",
    "retryable": false
  },
  "meta": {
    "envelope_version": "1.2.0",
    "timestamp": "2026-03-08T12:00:01Z",
    "cli_version": "0.8.10",
    "duration_ms": 45,
    "command": "run",
    "exit_code": 2
  }
}
```

**Envelope 1.2.0 additions** (present only when the failure came from an HTTP response):
- `error.http_status`: HTTP status code from the server (e.g., 400, 401, 429, 502)
- `error.server_code`: Server's own error code (e.g., `INSUFFICIENT_CREDITS`, `JOB_TYPE_RETIRED`)
- `error.retry_after`: Seconds to wait before retrying (on 429, 503, 504)
- `meta.exit_code`: Process exit code (see exit codes table below)

Test `.success` rather than checking a status string. `--json` prints the same `data` object without the envelope.

### Error Codes Reference

All error codes are prefixed with `ERR_`. Common codes:

| Code | Exit Code | Description | Recovery |
|------|-----------|-------------|----------|
| `ERR_INVALID_INPUT` | 2 | Bad parameters or validation failure | Check the input and options |
| `ERR_NOT_FOUND` | 3 | Resource not found | Verify ID with `ivybloom jobs list` |
| `ERR_UNAUTHORIZED` | 11 | No token or token invalid | Run `ivybloom auth login` |
| `ERR_FORBIDDEN` | 12 | Insufficient permissions | Contact support for access |
| `ERR_NOT_SUPPORTED` | 22 | Endpoint or job type retired | List current tools with `ivybloom tools list` |
| `ERR_JOB_NOT_FOUND` | 20 | Job ID not found | Check with `ivybloom jobs list` |
| `ERR_TOOL_NOT_FOUND` | 21 | Tool not available | List tools with `ivybloom tools list` |
| `ERR_JOB_TYPE_RETIRED` | 22 | Job type was retired | Check `ivybloom tools list` for alternatives |
| `ERR_API_RATE_LIMIT` | 31 | Too many requests | Wait and retry; check `retry_after` |
| `ERR_INSUFFICIENT_CREDITS` | 40 | Account out of credits | Run `ivybloom credits summary` |
| `ERR_UPSTREAM_UNAVAILABLE` | 32 | Service temporarily down | Retry after checking `ivybloom jobs list` |
| `ERR_API_CONNECTION` | 30 | Network connectivity issue | Check your connection with `ivybloom health` |
| `ERR_AUTH_REQUIRED` | 11 | Authentication needed | Run `ivybloom auth login` |
| `ERR_AUTH_EXPIRED` | 11 | Auth token expired | Run `ivybloom auth login` |
| `ERR_CONFIG_NOT_FOUND` | 10 | Config file missing | Run `ivybloom auth login` |

See `go/internal/errors/errors.go` in the CLI repo for the complete list.

---

## Script Mode

Script mode strips all interactive elements (spinners, colors, progress bars) for clean piping:

```bash
ivybloom jobs list --script --format json
```

Equivalent environment variable:

```bash
export IVYBLOOM_SCRIPT_MODE=1
ivybloom jobs list
```

---

## Output Formats

Control output format with `--format` or `--output-format`:

| Format | Flag | Description |
|--------|------|-------------|
| Table | `--format table` | Human-readable columns (default) |
| JSON | `--format json` | Pretty-printed JSON |
| JSON Compact | `--format json-compact` | Minified JSON (one line) |
| CSV | `--format csv` | Comma-separated values |
| YAML | `--format yaml` | YAML format |

---

## Dry-Run Modes

Validate jobs before submitting:

```bash
# Syntax validation only (fastest)
ivybloom run esmfold protein_sequence=MKLVFF --dry-run --dry-run-mode syntax

# Quick validation (checks parameter types)
ivybloom run esmfold protein_sequence=MKLVFF --dry-run --dry-run-mode quick

# Full validation (includes API checks)
ivybloom run esmfold protein_sequence=MKLVFF --dry-run --dry-run-mode full
```

---

## Global Automation Flags

| Flag | Description |
|------|-------------|
| `--agent` | JSON envelope output |
| `--script` / `-p` / `--simple` | Non-interactive output |
| `--json` | JSON output (no envelope) |
| `--format FORMAT` | Output format (table/json/csv/yaml) |
| `--force` / `-f` | Skip confirmation prompts |
| `--no-color` | Disable color output |
| `--trace-id ID` | Attach correlation ID for request tracking |
| `--timeout DURATION` | Override default timeout |

---

## Environment Variables

| Variable | Description |
|----------|-------------|
| `IVYBLOOM_AGENT_MODE=1` | Enable agent mode globally |
| `IVYBLOOM_SCRIPT_MODE=1` | Enable script mode globally |
| `NO_COLOR=1` | Disable color output |
| `IVYBLOOM_TRACE_ID` | Request correlation ID |
| `IVYBLOOM_API_KEY` | API key for authentication |
| `IVYBLOOM_DEBUG=1` | Enable debug output |

---

## Exit Codes

Every error returns a non-zero exit code that indicates the class of failure:

| Code | Meaning | Example |
|------|---------|---------|
| `0` | Success | Job submitted or completed |
| `1` | Generic error or server error (unhealthy) | Internal server error or 500 |
| `2` | Invalid input (caller's fault) | Bad flag, missing required parameter |
| `3` | Not found | Job ID or tool doesn't exist |
| `10` | Config or file missing | Auth config file missing |
| `11` | Authentication failed | No token, expired token, login required |
| `12` | Permission denied | Authenticated but user lacks access (403) |
| `13` | Session error | Session not found, create failed, expired |
| `14` | Campaign error | Campaign not found, required but missing |
| `15` | Message error | Message send or stream failed |
| `20` | Job not found | Job ID doesn't exist |
| `21` | Tool not found | Tool name not in registry |
| `22` | Not supported or retired | Job type was retired (410), endpoint doesn't exist (501) |
| `30` | Network error | Connection failed, DNS failed, timeout |
| `31` | Rate limited | Server returned 429; wait and retry (see `retry_after`) |
| `32` | Upstream unavailable | Gateway error (502, 503, 504) |
| `40` | Insufficient credits | Account balance cannot cover the cost (402) |

**Note:** Submit failures (e.g., idempotent resubmission of a failed job) never exit 0. Check the error envelope's `success` field.

---

## Job Submission & Idempotency

Every job submit request carries an `Idempotency-Key` header (a uuid v4, one per submit, reused on retries). This prevents duplicate submissions if the network fails after the server processes the request.

### Retry Policy

- **Automatic retries**: Only after 429 (rate limit) or 503 (service unavailable) responses that carry a `Retry-After` header
- **Not retried**: 502 (Bad Gateway) and 504 (Gateway Timeout) are never retried automatically
- **Idempotent replay**: If a submit fails, check `ivybloom jobs list` first to confirm whether the job was created, then resubmit. The server will recognize the same `Idempotency-Key` and return the original job (with `Idempotent-Replayed: true` header)
- **Never exit 0 on failure**: Submit failures always exit non-zero, even if the job was created but the response was lost

---

## CI/CD Patterns

### GitHub Actions

```yaml
name: Run Analysis

on: push

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install ivybloom CLI
        run: |
          curl -fsSL https://www.ivybiosciences.com/install | bash

      - name: Submit and Wait
        env:
          IVYBLOOM_API_KEY: ${{ secrets.IVYBLOOM_API_KEY }}
        run: |
          # Submit with agent mode, wait for completion
          RESULT=$(ivybloom run esmfold protein_sequence=MKLVFF --agent --wait)
          JOB_ID=$(echo "$RESULT" | jq -r '.data.job_id')
          STATUS=$(echo "$RESULT" | jq -r '.data.status')

          if [ "$STATUS" != "completed" ]; then
            echo "Job failed: $JOB_ID"
            exit 1
          fi

          # Download results
          ivybloom jobs download "$JOB_ID" --output ./results
```

### Batch Pipeline

```yaml
      - name: Batch Screen
        env:
          IVYBLOOM_API_KEY: ${{ secrets.IVYBLOOM_API_KEY }}
        run: |
          ivybloom batch submit screen.yaml --agent --wait
          ivybloom batch collect BATCH_ID --format csv --output results.csv
```

### Parsing Agent Output with jq

```bash
# Extract job ID from submission
JOB_ID=$(ivybloom run esmfold protein_sequence=MK --agent | jq -r '.data.job_id')

# Check job status
STATUS=$(ivybloom jobs status "$JOB_ID" --agent | jq -r '.data.status')

# List completed jobs
ivybloom jobs list --status completed --agent | jq -r '.data.jobs[].id'

# Get credit balance
BALANCE=$(ivybloom credits summary --agent | jq -r '.data.credits.balance')
```

---

## Read next

- [Jobs](/docs/cli/jobs) — Job submission and monitoring
- [Batch Processing](/docs/cli/batch) — Automated batch pipelines
- [MCP Integration](/docs/cli/mcp) — AI agent tool integration
- [Commands Reference](/docs/cli/commands) — Full command documentation
