---
name: build-ibmi-agent
description: >
  Build, create, scaffold, register, or add a custom IBM i agent on a running
  Ixora stack with `ixora agents create`. You describe the agent in a small
  `.agent.yaml` manifest (curated toolsets, model, instructions, optionally
  custom Db2 for i SQL tools) and create it — DB-backed, served immediately,
  no restart. Use to make a custom IBM i (Db2 for i) SQL agent, an agent for
  the ixora stack, or to update / improve / harden one. NOT the workbench
  `ibmi-agent-builder` skill (that scaffolds a standalone local app); this
  targets a running stack via `ixora agents`.
allowed-tools: Bash(ixora:*), Bash(uv:*), Bash(python3:*), Bash(docker:*), Bash(podman:*), Bash(command:*), Bash(cat:*), Bash(ls:*), Bash(grep:*), Bash(jq:*), Bash(find:*)
---

# build-ibmi-agent

Build a custom IBM i agent on a running Ixora stack. You write a small `.agent.yaml` manifest and create it with `ixora agents create`. The agent is DB-backed and served immediately — no restart. Keep the manifest in git; it's the source of truth, the stack just holds a copy.

**Discovery loop:** when a flag or shape is unclear, run `<cmd> --help`, read it, then act. Don't guess. Start with `ixora agents --help` and `ixora agents create --help`.

## Three tools, kept straight

| Tool | Role |
|---|---|
| **`ixora`** | platform CLI — create / run / inspect the agent on the stack |
| **`ibmi`** | IBM i CLI — introspect Db2 for i schema while designing **custom** SQL tools |
| **`$AB`** | bundled `scripts/container_ibmi.py` — runs the **container's** `ibmi` so the schema you design against is the one the agent queries |

Use `$AB` only for custom SQL tools, and only on **stack** instances — external and workspace instances have no local `api-<id>` container, so `$AB` rejects them. Never the host `ibmi` — its registry is independent of Ixora and may point at a different box ([introspection.md](references/introspection.md)). A toolset-only agent needs no introspection at all.

## Preflight

```bash
ixora instances list          # every configured instance, its kind, and a live indicator
ixora agents toolsets list    # the curated IBM i toolset catalog (JSON)
ixora agents create --help    # the create surface
```

`$AB` is `scripts/container_ibmi.py` in this skill's own directory. If you need it for custom tools, set it per command (shell state doesn't persist):

```bash
AB="<this skill's dir>/scripts/container_ibmi.py"
uv run "$AB" resolve --instance <id>    # confirm which container the ibmi passthrough hits
```

Pass `--instance <id>` to target one of several configured instances; omit it when only one is configured. The target must be a **stack** instance (`ixora instances list` shows each instance's kind).

## Build

Confirm the plan with the user before creating — it mutates the running stack.

**Most agents need only toolsets.** Pick the ones that cover the data (`ixora agents toolsets list`, then `ixora agents toolsets get <name>` to peek inside one), write the manifest, create. Only design custom SQL tools when no curated toolset covers the query.

Write `<agent-id>.agent.yaml`. Lead the instructions with *prefer the named SQL tools; fall back to `validate_and_run_sql` only when none fit.* Manifest keys, `options`, `knowledge`, `stage`: [manifest.md](references/manifest.md).

Show the manifest, get explicit confirmation, then create:

```bash
ixora agents create -f <agent-id>.agent.yaml    # custom tools in a separate file: add --ibmi-tools <file>
# -> Success: Created agent '<agent-id>' (stage=published, version=1)
```

Add `--dry-run` to print the resolved spec without touching the server. Use `ixora agents apply -f <file>` for an idempotent create-or-update.

### Custom SQL tools (only when needed)

Introspect the **real** schema through `$AB ibmi` — Db2 for i names differ per system, so never guess. Run `-- --help` if you're unsure which subcommand exists.

```bash
uv run "$AB" ibmi --instance <id> -- tables <SCHEMA>                            # start here when the schema is named
uv run "$AB" ibmi --instance <id> -- validate "<the tool's exact statement>"    # syntax + objects, no execution
```

Then author **read-only, parameterized** tools. The shape is strict — SQL field is `statement` (not `sql`), every tool needs `source: default` + a `description`. Full shape, gotchas, and the introspection surface: [tool-yaml.md](references/tool-yaml.md), [introspection.md](references/introspection.md).

## Verify

Run the agent. The printed answer is the smoke test:

```bash
ixora agents run <agent-id> "<a focused question>" --session-id smoke-1 --bypass-confirmations
```

To see **what happened** — which tools fired, not just the answer — look at the session or the trace:

```bash
ixora sessions runs smoke-1                       # per-run messages: tool calls + results
ixora traces list --agent-id <agent-id>           # find the run's trace, then `ixora traces get <trace_id> --json`
```

Pin the session with `--session-id <name>` (that name *is* the session id you pass to `sessions runs`) so you know which one to inspect. The verify run is the real proof: schema checks catch SQL syntax, but parameter-type errors surface only at run time. A run's `run_id` is **not** a trace id — the mapping is in [introspection.md](references/introspection.md). Keep the question focused; a broad prompt can exceed the default request timeout (raise it with `--timeout`). Then give the user a couple of example runs to try, each exercising a different tool.

## Update / improve

The manifest is the editable source of truth. Re-apply it, or sparse-edit one field (run `ixora agents update --help` for the fields):

```bash
ixora agents apply -f <agent-id>.agent.yaml                 # idempotent: created / updated / unchanged
ixora agents update <agent-id> --instructions "…"           # sparse: needs >=1 field, rest preserved
```

Either publishes a new version immediately — no restart. To stage without serving, add `--stage draft`, then `--stage published` to promote. To test and improve an agent, use the probe -> judge -> fix loop in [hardening.md](references/hardening.md). `ixora agents delete <agent-id>` frees the id and removes the server-side copy.

## Command surface

`ixora agents` has definition verbs (create, apply, update, delete) and run/inspect verbs (run, runs, continue, pending, resume, cancel, list, get, toolsets). Run `ixora agents --help` for the full list and `ixora agents <verb> --help` for each verb's flags.

`$AB` has two subcommands — `resolve` (confirm the target) and `ibmi` (the container passthrough). Run `uv run "$AB" --help` for both. It is only for introspection; all agent definition goes through `ixora agents`.

## Hard rules

- **`model` is always `provider:id`** (e.g. `anthropic:claude-sonnet-4-6`) — never a bare name.
- **Unknown manifest keys are rejected**, not dropped (a typo errors with the valid-keys list).
- **`tools` and `dependencies` are server-managed** — never put them in `options`. The top-level `db:` **is** yours to set (defaults to the primary database).
- **A draft agent won't appear in `ixora agents list`** (served only), though it shows in `ixora components list`. Re-apply `--stage published` to serve it.
