# Agents & Workflows

## Overview

Glee separates two concepts for subagent orchestration:

1. **Agents**: Reusable workers (humans or AI can define agents)
2. **Workflows**: Orchestration of agent calls (humans or AI can define workflows)

**AI-native**: Agents can define other agents and workflows, enabling fully autonomous operation.

This is simpler than Claude Code's multiple markdown file types (AGENTS.md, .claude/agents/*.md, plugins, skills).

## Comparison with Claude Code

```
Claude Code:
├── AGENTS.md              # Project instructions
├── .claude/agents/*.md    # Subagents
├── plugins                # External integrations
└── skills                 # Task-specific capabilities

Glee (simpler):
├── AGENTS.md              # Project instructions (same)
├── .glee/agents/*.yml     # Reusable workers
└── .glee/workflows/*.yml  # Orchestration (optional)
```

**Key insight**: All these concepts are just markdown files in Claude Code. Glee uses a unified YAML format and separates workers (agents) from orchestration (workflows).

## Agents

Agents are **reusable workers**. They can be defined by:
- **Humans**: Manual creation of `.glee/agents/*.yml`
- **AI**: Agents can define other agents (AI-native, fully autonomous)

### Format

```yaml
# .glee/agents/security-scanner.yml
name: security-scanner
description: Scan code for security vulnerabilities

# Which CLI to use (optional, auto-selects if not specified)
agent: codex

# The system prompt
prompt: |
  You are a security expert. Analyze the given code for:
  - SQL injection
  - XSS vulnerabilities
  - Authentication issues
  - Secrets in code

  Report findings with severity levels: HIGH, MEDIUM, LOW.

# Optional settings
timeout_mins: 5
max_output_kb: 50
```

### Import from Other Formats

```bash
# Import from Claude Code
glee agents import --from claude
# Reads .claude/agents/*.md → .glee/agents/*.yml

# Import from Gemini CLI
glee agents import --from gemini
# Reads .gemini/agents/*.toml → .glee/agents/*.yml
```

Import is **one-way** (source → glee). Glee never writes back to `.claude/` or `.gemini/`.

### Source Tracking

Imported agents have a `source` field:

```yaml
name: security-reviewer
description: Security code reviewer
agent: claude
prompt: |
  You are a security expert...

# Only present for imported agents
source:
  from: claude
  file: .claude/agents/security-reviewer.md
  imported_at: "2025-01-09T15:00:00Z"
```

Native Glee agents don't have a `source` field.

## Workflows

Workflows define **how agents work together**. They can be defined by humans OR generated by AI.

### Format

```yaml
# .glee/workflows/full-review.yml
name: full-review
description: Complete code review with security and performance analysis

# Sequence of steps
steps:
  - agent: security-scanner
    inputs:
      target_file: ${target}

  - agent: performance-analyzer
    inputs:
      target_file: ${target}

  - agent: code-reviewer
    inputs:
      target_file: ${target}
      security_report: ${steps[0].output}
      performance_report: ${steps[1].output}

# How to run steps
execution: sequential  # or: parallel, dag
```

### Parallel Execution

```yaml
# .glee/workflows/parallel-scan.yml
name: parallel-scan
description: Run multiple scanners in parallel

steps:
  - agent: security-scanner
    parallel_group: scanners

  - agent: lint-checker
    parallel_group: scanners

  - agent: type-checker
    parallel_group: scanners

  # This runs after all scanners complete
  - agent: report-aggregator
    inputs:
      reports: ${parallel_group.scanners.outputs}

execution: parallel
```

### Step Output Schema

Each step produces a `StepResult` object:

```typescript
interface StepResult {
  status: "success" | "error" | "timeout" | "skipped";
  output: string | null;       // Agent output (null on error)
  error: string | null;        // Error message (null on success)
  duration_ms: number;
  agent: string;               // Agent or workflow name
  step_index: number;
}
```

**Accessing outputs:**
- `${steps[0].output}` — Output string from step 0 (empty string if step failed)
- `${steps[0].status}` — Status of step 0
- `${steps[0].error}` — Error message if step 0 failed

### Parallel Group Output Schema

Parallel groups aggregate results from all steps in the group:

```typescript
interface ParallelGroupResult {
  status: "success" | "partial" | "error";  // partial = some succeeded
  outputs: StepResult[];                     // All step results
  succeeded: StepResult[];                   // Only successful steps
  failed: StepResult[];                      // Only failed steps
}
```

**Accessing parallel outputs:**
- `${parallel_group.scanners.outputs}` — Array of all StepResults
- `${parallel_group.scanners.succeeded}` — Only successful results
- `${parallel_group.scanners.status}` — "success" if all passed, "partial" if some failed, "error" if all failed

### Failure Semantics

| Execution Mode | On Step Failure | Behavior |
|----------------|-----------------|----------|
| `sequential` | Stop workflow | Subsequent steps are skipped; workflow returns error |
| `parallel` | Continue others | Failed step marked as error; workflow continues |
| `dag` | Skip dependents | Steps depending on failed step are skipped |

**Override with `on_error`:**

```yaml
steps:
  - agent: security-scanner
    on_error: continue    # continue | stop | skip_dependents (default: stop)

  - agent: code-reviewer
    inputs:
      # Handle potential missing output from previous step
      security_report: ${steps[0].output ?? "No security scan available"}
```

**Null coalescing:** Use `${expr ?? default}` to provide fallback values when a step fails.

### Nested Workflows

Workflows can contain other workflows. This enables modular composition.

```yaml
# .glee/workflows/run-restaurant.yml
name: run-restaurant
description: Daily operations for a restaurant

steps:
  - workflow: accounting          # Another workflow
  - workflow: purchasing          # Another workflow
  - workflow: serve-customers     # Another workflow (more specific scope)
  - workflow: cleaning            # Another workflow
```

```yaml
# .glee/workflows/serve-customers.yml
name: serve-customers
description: Handle customer service flow

steps:
  - agent: order-taker
    inputs:
      channel: ${channel}  # in-store, drive-thru, app

  - agent: payment-processor
    inputs:
      order: ${steps[0].output}

  - agent: food-preparer
    inputs:
      order: ${steps[0].output}

  - agent: delivery-handler
    inputs:
      order: ${steps[0].output}
      food: ${steps[2].output}
```

**Key insight**: `serve-customers` is a standalone workflow with its own scope and detailed steps. The parent workflow (`run-restaurant`) doesn't need to know the details — it just invokes the sub-workflow.

This is how complex systems are built:
- **Agents**: Atomic workers (do one thing)
- **Workflows**: Compose agents and other workflows (recursive structure)

### Execution Safeguards

Nested and AI-generated workflows require safeguards to prevent runaway execution:

#### Cycle Detection

Glee detects workflow cycles at **validation time** (before execution):

```
Error: Workflow cycle detected: run-restaurant → serve-customers → run-restaurant
```

Cycles are checked by building a dependency graph from all `workflow:` references. If a cycle is found, the workflow fails validation and won't execute.

#### Depth Limits

Maximum nesting depth prevents stack exhaustion:

```yaml
# .glee/config.yml
workflows:
  max_depth: 5          # Default: 5 levels of nesting
```

When depth is exceeded:
```
Error: Workflow depth limit exceeded (5): run-restaurant → purchasing → vendor-mgmt → ...
```

#### Execution Budgets

Budgets prevent runaway fan-out and resource exhaustion:

```yaml
# .glee/config.yml
workflows:
  budgets:
    max_steps: 100            # Max total steps across all nested workflows
    max_parallel: 10          # Max concurrent agents/workflows
    max_runtime_mins: 30      # Kill workflow after 30 minutes
    max_cost_usd: 5.00        # Stop if estimated API cost exceeds $5 (future)
```

**Budget tracking is hierarchical**: A parent workflow's budget is shared with all nested workflows. If a nested workflow exhausts the budget, the entire tree stops.

```typescript
interface ExecutionBudget {
  steps_remaining: number;
  parallel_slots: number;
  runtime_deadline: Date;
  cost_remaining_usd: number | null;
}
```

**On budget exhaustion:**

| Budget Type | Behavior |
|-------------|----------|
| `max_steps` | Workflow returns error; remaining steps skipped |
| `max_parallel` | New parallel steps wait until slots free up |
| `max_runtime_mins` | All running agents killed; workflow returns timeout |
| `max_cost_usd` | Workflow paused; user prompted to continue or abort |

#### AI-Generated Workflow Constraints

AI-generated workflows have additional restrictions:

1. **Cannot nest other workflows**: Only `agent:` steps allowed, not `workflow:`
2. **Reduced budgets**: Uses `workflows.ai_generated_budgets` (lower defaults)
3. **Approval required**: User must approve before execution

```yaml
# .glee/config.yml
workflows:
  ai_generated_budgets:
    max_steps: 10             # Much lower than human-defined
    max_parallel: 3
    max_runtime_mins: 5
```

### AI-Generated Workflows (Future)

> **Note**: This is a Phase 4 feature (v0.6+). Not yet implemented.

The main agent (Claude, etc.) will be able to generate workflows on-the-fly using `glee_workflow_create`:

```python
# Main agent creates and executes a workflow dynamically
glee_workflow_create(
    name="review-auth-changes",
    definition={
        "description": "Review authentication changes",
        "steps": [
            {"agent": "security-scanner", "inputs": {"focus": "auth"}},
            {"agent": "performance-analyzer", "inputs": {"focus": "auth"}}
        ],
        "execution": "parallel"
    }
)

# Then execute it
glee_workflow(
    name="review-auth-changes",
    inputs={"target": "src/api/auth.py"}
)
```

This will allow AI to compose agents without human-defined workflow files.

## Tools

See [tools.md](tools.md) for the full Tools documentation.

Tools are external capabilities defined in `.glee/tools/<tool_name>/tool.yml`. Agents can also create new tools (AI-native).

## MCP Tools

### `glee_task`

Spawn an agent to execute a task:

```python
glee_task(
    description="Find API endpoints",           # Short (3-5 words)
    prompt="Search for all REST endpoints...",  # Full task prompt
    agent_name="explore",                       # Optional: subagent from .glee/agents
    agent_cli="codex",                          # Optional: run CLI directly (ignored if agent_name is set)
    background=False,                           # Optional: run in background
    session_id=None                             # Optional: resume session
)
```

### `glee_workflow` (future)

Execute a named workflow:

```python
glee_workflow(
    name="full-review",
    inputs={"target": "src/api/auth.py"}
)
```

### `glee_agents_list`

List available agents:

```python
glee_agents_list()
# Returns:
# [
#   {"name": "security-scanner", "source": "native"},
#   {"name": "code-reviewer", "source": "claude"},
#   {"name": "performance-analyzer", "source": "gemini"}
# ]
```

## Context Injection

When spawning an agent, Glee automatically injects context:

1. **AGENTS.md**: Project instructions from root directory
2. **Memories**: Relevant memories from `glee_memory_search`
3. **Session history**: Previous conversation (if resuming)

```python
# Glee does this internally:
agents_md = read_file("AGENTS.md")
memories = glee_memory_search(query=task_description)
session = load_session(session_id) if session_id else None

full_prompt = f"""
<glee:context source="AGENTS.md" trusted="true">
{escape_xml_tags(agents_md)}
</glee:context>

<glee:context source="memory" trusted="false">
{escape_xml_tags(memories)}
</glee:context>

<glee:context source="session:{session_id}" trusted="false">
{escape_xml_tags(session_history) if session else ""}
</glee:context>

<glee:user_prompt>
{user_prompt}
</glee:user_prompt>
"""
spawn_subprocess(agent_cli, full_prompt)
```

### Security: Prompt Injection Mitigation

Context from multiple sources is merged with provenance markers to prevent prompt injection:

- **Provenance markers**: `<glee:context source="..." trusted="...">` tags identify each source
- **Tag escaping**: `escape_xml_tags()` prevents content from breaking out of its container
- **Trust levels**: AGENTS.md is trusted (maintainer-controlled); memories and session history are untrusted

See [subagents.md](subagents.md#prompt-injection-mitigation) for details.

## Session Management

CLI agents (codex, claude, gemini) are stateless. Glee stores conversation history:

```
.glee/agent_sessions/
└── task-a1b2c3d4.json
```

```json
{
  "session_id": "task-a1b2c3d4",
  "agent_name": "security-scanner",
  "agent_cli": "codex",
  "created_at": "2025-01-09T15:00:00",
  "messages": [
    {"role": "user", "content": "Search for all REST endpoints"},
    {"role": "assistant", "content": "Found 5 endpoints..."}
  ]
}
```

Resume a session:

```python
glee_task(
    session_id="task-a1b2c3d4",
    prompt="Now document each endpoint"
)
# Agent receives full conversation history
```

## Implementation Phases

### Phase 1: glee_task (v0.3)
- [x] Design docs (subagents.md, workflows.md, tools.md)
- [x] `glee_task` MCP tool - spawn CLI agents (codex, claude, gemini)
- [x] Session management (generate ID, store context)
- [x] Context injection (AGENTS.md + memories)
- [x] Basic logging to `.glee/stream_logs/`

### Phase 2: Tools (v0.4)
- [ ] Tool manifest format (directory tool.yml)
- [ ] `glee_tool` MCP tool (execute tools)
- [ ] `glee_tool_create` MCP tool (AI creates tools)
- [ ] Built-in tools: web_search, http_request

### Phase 3: Agents (v0.5)
- [ ] `.glee/agents/*.yml` format
- [ ] `glee_agent_create` MCP tool (AI creates agents)
- [ ] `glee agents import` from Claude/Gemini formats
- [ ] Agent selection heuristics

### Phase 4: Workflows (v0.6+)
- [ ] `.glee/workflows/*.yml` format
- [ ] `glee_workflow` MCP tool
- [ ] Nested workflows
- [ ] Parallel/DAG execution
