---
sidebar_position: 2
title: Agent strategies
---

# Agent strategies

A **strategy** is the bridge between a node and a real coding-agent CLI. The framework ships with five built-in strategies; you can also write your own.

## Built-ins

| Strategy | Backed by | When to pick it |
|---|---|---|
| `cursor` | `cursor-agent` CLI | Fast, file-aware, great default for code tasks |
| `claude` | `@anthropic-ai/claude-agent-sdk` | Best reasoning, deep tool-use loops, large context |
| `codex` | `@openai/codex` CLI | Strong general-purpose, good for verification nodes |
| `gemini` | `@google/gemini-cli` | When you specifically want Gemini's behavior |
| `assistant` | OpenAI Assistants API | Stateful conversations, retrieval, file uploads |

## Selecting per node

Two ways:

```js
// 1. Per-node config — wins over everything else
graph.addNode('plan', { prompt, outputSchema, agent: 'claude' });

// 2. Project default — falls through if no per-node override
// .zibby.config.mjs
export default {
  agent: { default: 'cursor' },
};
```

The resolution order: `node.agent` → `state.agentType` → `process.env.AGENT_TYPE` → project config default.

## Models

Each agent CLI has its own model selector. Override it via:

```js
// Per-node model
graph.addNode('plan', {
  prompt,
  outputSchema,
  agent: 'claude',
  model: 'claude-opus-4-6',
});

// Or globally per-agent in .zibby.config.mjs
export default {
  agent: {
    default: 'cursor',
    claude: { model: 'claude-opus-4-6' },
    cursor: { model: 'auto' },
  },
};
```

`auto` (the default for cursor/claude/gemini) uses the agent CLI's own current default — which tracks the latest stable model.

## Bring your own

The `AgentStrategy` base class is two methods:

```js
import { AgentStrategy, registerStrategy } from '@zibby/agent-workflow';

class MyAgent extends AgentStrategy {
  constructor() { super('mine', 'My custom agent', 100); }

  canHandle(_context) {
    return Boolean(process.env.MY_API_KEY);
  }

  async invoke(prompt, { schema, model }) {
    const raw = await fetch('https://my.api/chat', {
      method: 'POST',
      body: JSON.stringify({ prompt, model: model ?? 'default' }),
    }).then(r => r.text());

    return { raw, structured: schema.parse(JSON.parse(raw)) };
  }
}

registerStrategy(new MyAgent());
```

Then a node can use it:

```js
graph.addNode('plan', { prompt, outputSchema: Plan, agent: 'mine' });
```

The framework ships **zero** agent strategies bundled — `@zibby/agent-workflow` is BYO. The five built-ins above live in `@zibby/core`, which is what `zibby agent new` scaffolds and what the cloud runtime preloads.

## Authentication

| Strategy | Env var | Alternative |
|---|---|---|
| `cursor` | `CURSOR_API_KEY` | `cursor-agent login` |
| `claude` | `ANTHROPIC_API_KEY` | — |
| `codex` | `OPENAI_API_KEY` | — |
| `gemini` | `GOOGLE_API_KEY` | — |
| `assistant` | `OPENAI_API_KEY` | — |

In Zibby Cloud, you have two options:

- **Project-wide credentials**: set once on the project record (dashboard → Project → Secrets) — every agent in the project uses them.
- **Per-agent overrides**: set on a single agent via [`PUT /workflows/<uuid>/env`](../cloud/env-vars) — useful when one agent needs a different `ANTHROPIC_API_KEY` from the rest of the project, or when one agent needs to talk to multiple agent vendors with their own keys.

Agent env wins over project secrets on conflict (last-write-wins inside the Fargate task).
