274 lines
14 KiB
Markdown
274 lines
14 KiB
Markdown
---
|
|
name: multi-agent-mux-create
|
|
description: "Create a new agent session (claude, antigravity/agy) in a dedicated herdr session for context-preserving long-running work. Always creates a herdr session — never backgrounds with nohup/disown. Writes the new session to .mam/agent-sessions.yaml. Use when you want to start a fresh agent (no prior UUID) for a new project workspace."
|
|
version: 1.0.0
|
|
author: godopu
|
|
license: MIT
|
|
platforms: [linux, macos]
|
|
environments: [terminal, herdr]
|
|
metadata:
|
|
hermes:
|
|
tags: [agent, herdr, claude, antigravity, agy, multi-agent, context, session]
|
|
related_skills: [multi-agent-mux-resume, multi-agent-mux-stop, multi-agent-mux-monitor, claude-code]
|
|
prereq_skills: [claude-code]
|
|
---
|
|
|
|
# Multi-Agent Create — Start a Fresh Agent in a herdr Session
|
|
|
|
> **Companion skills**: `multi-agent-mux-resume` (resume an existing UUID), `multi-agent-mux-stop` (terminate), `multi-agent-mux-monitor` (live status).
|
|
> **Single source of truth**: `./.mam/agent-sessions.yaml` (this skill writes to it; never read it ad-hoc — go through this skill).
|
|
|
|
## What this skill does
|
|
|
|
Spawn a new agent (`claude` or `agy`/antigravity-cli) in a **dedicated herdr session** for context-preserving long-running work. The herdr session is the *container*; the agent's session ID is *data* inside the container. **This skill creates the container + starts the agent — but does not resume an old conversation** (use `multi-agent-mux-resume` for that).
|
|
|
|
For all agents: the herdr session name is produced by **`lib.sh::derive_session_name`** — the single source of truth shared by create/resume/stop/status/monitor (P0-A). The rule (verbatim from the function):
|
|
|
|
> slug = the **two trailing path components** of the absolute workspace, `_`→`-`, lowercased, joined with `-`; name = `<slug>-creator-<agent>`.
|
|
|
|
So `$WORKSPACE_ROOT/landing_page/refer_landing_page` + `claude` → `landing-page-refer-landing-page-creator-claude`. The workspace basename (`refer_landing_page`) **is** included; the hand-written historical entry that dropped it (`lab-landing-page-creator-claude`) was the bug, not the convention.
|
|
|
|
## Pre-flight checks
|
|
|
|
Before doing anything, verify the environment:
|
|
|
|
```bash
|
|
# 1) herdr available and isolated server status
|
|
command -v herdr || { echo "ERROR: herdr not installed"; exit 1; }
|
|
echo "Herdr session name: ${HERDR_SESSION_NAME:-default}"
|
|
|
|
# 2) claude / agy available
|
|
command -v claude # required for --agent claude
|
|
command -v agy # required for --agent agy
|
|
|
|
# 3) claude auth (if --agent claude)
|
|
claude auth status 2>&1 | python3 -c "import json,sys; d=json.load(sys.stdin); assert d.get('loggedIn'), 'claude not logged in'"
|
|
|
|
# 4) target workspace exists
|
|
test -d "$WORKSPACE" || { echo "ERROR: workspace $WORKSPACE not a directory"; exit 1; }
|
|
```
|
|
|
|
If any check fails → abort with a non-zero exit and report the reason (automated path) or report to user (interactive path). Do not proceed with a half-broken setup.
|
|
|
|
## Standard names
|
|
|
|
- **herdr session name**: `derive_session_name <workspace> <agent>` (lib.sh)
|
|
- `<workspace-slug>` = `basename $(dirname $WORKSPACE)` `-` `basename $WORKSPACE` (lowercase, `_`→`-`)
|
|
- examples: `landing-page-refer-landing-page-creator-claude`, `paper-pdf2md-creator-agy`
|
|
- never re-derive this by hand — source lib.sh and call the function
|
|
- **wrapper script** (claude only): `~/.local/bin/<workspace-slug>-creator-claude`
|
|
- contents: herdr new-session with `claude` inside, auto-handles trust/bypass dialogs
|
|
- see `<workdir>/agent_sessions.md` for the canonical wrapper template
|
|
|
|
## Herdr Server Isolation (격리 서버)
|
|
|
|
When running multiple agent sessions alongside other workflows (e.g., cmux, background workers, manual herdr sessions), sharing the default herdr server can lead to session name conflicts, monitoring clutter, and accidental destruction of user sessions via global commands.
|
|
|
|
To prevent this, you can run this skill inside an **isolated herdr server** using the `HERDR_SERVER_NAME` environment variable or the `--herdr-server <name>` flag (opt-in).
|
|
|
|
Under the hood this now maps to a real, separate herdr **session** (`herdr --session <name>` — its own socket, its own `agent list`/`workspace list`, completely invisible to the default session and vice versa), not just a workspace label inside the same server. `lib.sh`'s shim bootstraps the named session's server headlessly (`herdr --session <name> server`, backgrounded) the first time it's needed, and scopes every subsequent herdr call to it automatically — this headless bootstrap is what lets it work even when the skill itself is running from inside another herdr-managed pane (a plain interactive `herdr --session <name>` launch is blocked there by herdr's "nested herdr is disabled" guard; headless `server` mode isn't).
|
|
|
|
### How to use
|
|
1. **Via Environment Variable**:
|
|
```bash
|
|
export HERDR_SERVER_NAME=multi-agent-canary
|
|
# All subsequent commands (create, status, stop, etc.) will run in the isolated 'multi-agent-canary' herdr server.
|
|
```
|
|
2. **Via Option Flag**:
|
|
```bash
|
|
bash scripts/create_session.sh --workspace /path/to/project --agent claude --role developer --herdr-server multi-agent-canary
|
|
```
|
|
3. **Submit Job Integration**:
|
|
You can automatically register a delegated job with a prompt when creating a session:
|
|
```bash
|
|
bash scripts/create_session.sh --workspace /path/to/project --agent claude --role developer --submit-job "Task prompt here"
|
|
```
|
|
4. **Onboard Integration**:
|
|
You can automatically submit a project alignment/orientation job to the new agent when creating a session:
|
|
```bash
|
|
bash scripts/create_session.sh --workspace /path/to/project --agent claude --role developer --onboard
|
|
```
|
|
|
|
### Recommended Alias
|
|
You can set an alias in your shell to easily query sessions on the isolated server:
|
|
To prevent this, you can run this skill inside an **isolated herdr session** using the `HERDR_SESSION_NAME` environment variable or the `--herdr-session <name>` flag (opt-in).
|
|
|
|
```bash
|
|
# Explicit custom session
|
|
export HERDR_SESSION_NAME=multi-agent-canary
|
|
bash .agents/skills/multi-agent-mux-create/scripts/create_session.sh \
|
|
--workspace /path/to/project --agent claude --role Developer
|
|
|
|
# Or via flag
|
|
bash .agents/skills/multi-agent-mux-create/scripts/create_session.sh \
|
|
--workspace /path/to/project --agent claude --role Developer --herdr-session multi-agent-canary
|
|
```
|
|
|
|
Why use `--herdr-session`?
|
|
|
|
- By default, all skills target `default` herdr session socket — fine for single-workspace use.
|
|
- By using an isolated session via `HERDR_SESSION_NAME`, your agent sessions are completely separated from your default user workspace, ensuring 0% interference — this is now backed by a genuinely separate `herdr` session/socket, not merely a workspace label.
|
|
- To deliberately tear down an *entire* isolated group at once (all its workspaces and agents), use `herdr session stop <HERDR_SESSION_NAME>` followed by `herdr session delete <HERDR_SESSION_NAME>` — this only affects that named session, never the default one.
|
|
|
|
---
|
|
|
|
## Output format
|
|
|
|
When invoked, the script creates or updates `./.mam/agent-sessions.yaml` with:
|
|
|
|
```yaml
|
|
herdr_sessions:
|
|
- name: <workspace>-creator-<agent> # E.g. landing-page-creator-claude
|
|
status: running # Initial status for a freshly created agent
|
|
role: Developer
|
|
herdr_session_created_at: '2026-08-04T12:00:00Z'
|
|
herdr_session_epoch: 1785844800
|
|
herdr_session: <HERDR_SESSION_NAME> # Isolated session name (default: 'mam-<ws-slug>')
|
|
delegate_job_id: null
|
|
pane:
|
|
index: 0
|
|
pid: 12345
|
|
cmd: claude
|
|
cmd_full: claude --dangerously-skip-permissions
|
|
cwd: /path/to/project
|
|
start_command: "HERDR_SESSION_NAME=<herdr_session> herdr new-session -d -s <SESSION_NAME> -x 140 -y 40 -c <WORKSPACE> <CMD_FULL>"
|
|
attach_command: "HERDR_SESSION_NAME=<herdr_session> herdr agent attach <SESSION_NAME>"
|
|
kill_command: "HERDR_SESSION_NAME=<herdr_session> herdr kill-session -t <SESSION_NAME>"
|
|
```
|
|
|
|
## Workflow
|
|
|
|
```bash
|
|
WORKSPACE=/path/to/project
|
|
AGENT=claude # or agy
|
|
source .agents/skills/lib.sh
|
|
SESSION_NAME="$(derive_session_name "$WORKSPACE" "$AGENT")"
|
|
|
|
# 1. If session already alive, fail fast
|
|
herdr has-session -t "$SESSION_NAME" 2>/dev/null && {
|
|
echo "ERROR: herdr session '$SESSION_NAME' already exists. Use multi-agent-mux-resume to attach or multi-agent-mux-stop first."
|
|
exit 1
|
|
}
|
|
|
|
# 2. Spawn the herdr session with the agent inside
|
|
case "$AGENT" in
|
|
claude)
|
|
# Use the wrapper if it exists, else inline herdr new-session
|
|
# Use the wrapper if it exists (LOCAL_BIN env var overrides default $HOME/.local/bin)
|
|
local_bin="${LOCAL_BIN:-$HOME/.local/bin}"
|
|
if [ -x "$local_bin/$SESSION_NAME" ]; then
|
|
nohup "$local_bin/$SESSION_NAME" >/dev/null 2>&1 &
|
|
else
|
|
herdr new-session -d -s "$SESSION_NAME" -x 140 -y 40 -c "$WORKSPACE" "claude"
|
|
fi
|
|
;;
|
|
agy)
|
|
herdr new-session -d -s "$SESSION_NAME" -x 140 -y 40 -c "$WORKSPACE" "agy --dangerously-skip-permissions"
|
|
;;
|
|
*) echo "ERROR: --agent must be claude or agy, got: $AGENT"; exit 2 ;;
|
|
esac
|
|
|
|
# 3. Wait for agent TUI to be ready (varies: claude ~5s, agy ~3s)
|
|
sleep 6
|
|
|
|
# 4. Capture pane metadata
|
|
PANE_PID=$(herdr list-panes -t "$SESSION_NAME" -F '#{pane_pid}')
|
|
PANE_CWD=$(herdr list-panes -t "$SESSION_NAME" -F '#{pane_current_path}')
|
|
PANE_CMD=$(herdr list-panes -t "$SESSION_NAME" -F '#{pane_current_command}')
|
|
# `herdr list-sessions` doesn't exist (real or shimmed) — we just spawned this
|
|
# session ourselves, so stamp the epoch locally instead of round-tripping herdr.
|
|
HERDR_EPOCH=$(date +%s)
|
|
```
|
|
|
|
## Registering the session in agent-sessions.yaml
|
|
|
|
After spawn, append a new `herdr_sessions[]` entry to `.mam/agent-sessions.yaml`:
|
|
|
|
```yaml
|
|
- name: <SESSION_NAME>
|
|
status: running
|
|
herdr_session_created_at: 2026-06-17T...Z # ISO 8601 UTC
|
|
herdr_session_epoch: <HERDR_EPOCH>
|
|
herdr_server: <HERDR_SERVER_NAME> # Isolated server name (default: 'default')
|
|
pane:
|
|
index: 0
|
|
pid: <PANE_PID>
|
|
cmd: <AGENT> # 'claude' or 'agy'
|
|
cmd_full: <full command line, see table below>
|
|
cwd: <PANE_CWD>
|
|
tui: # only for claude
|
|
model: <from TUI status>
|
|
provider: <from TUI status>
|
|
plan: <from TUI status>
|
|
account: <from TUI status>
|
|
version: <from TUI status>
|
|
start_command: "HERDR_SERVER_NAME=<herdr_server> herdr new-session -d -s <SESSION_NAME> -x 140 -y 40 -c <WORKSPACE> <CMD_FULL>"
|
|
attach_command: "HERDR_SERVER_NAME=<herdr_server> herdr agent attach <SESSION_NAME>"
|
|
kill_command: "HERDR_SERVER_NAME=<herdr_server> herdr kill-session -t <SESSION_NAME>"
|
|
# All three require `source .agents/skills/lib.sh` first — `new-session`/`kill-session`
|
|
# are tmux-compat pseudo-commands the shim translates, and `HERDR_SERVER_NAME` is what
|
|
# the shim reads to route to the right isolated herdr *session* (real `herdr` has no
|
|
# env-var-based scoping of its own; `herdr_server: default` needs no prefix at all).
|
|
```
|
|
|
|
`cmd_full` per agent (this is the actual command line in the pane, not the resume command):
|
|
|
|
| agent | cmd_full |
|
|
|---|---|
|
|
| claude (interactive) | `claude` |
|
|
| agy (interactive) | `agy --dangerously-skip-permissions` |
|
|
|
|
Use the `agent-sessions-yaml-edit` script in `scripts/` to safely append (preserves comments + format):
|
|
|
|
```bash
|
|
bash .agents/skills/multi-agent-mux-create/scripts/create_session.sh \
|
|
--workspace "$WORKSPACE" --agent "$AGENT" --role "$ROLE" --session "$SESSION_NAME"
|
|
```
|
|
|
|
The script handles the YAML append, pane capture, and the `last_visible_status` placeholder.
|
|
|
|
## Pitfalls
|
|
|
|
- **Don't use `nohup`/`disown`/`setsid` for the agent itself** — those background the agent outside herdr. The whole point of this skill is *the herdr session is the supervisor*. `nohup` is OK only for *launching the wrapper* (which itself creates the herdr session via `herdr new-session -d`).
|
|
- **Don't trust `--session-id <uuid>` flags blindly** — claude/agy may not accept a fixed session id on first spawn. The session id is *assigned* on first user message; you can read it back from `~/.claude/projects/.../session.jsonl` headers or `~/.gemini/.../cache/last_conversations.json` AFTER the first message.
|
|
- **Wrapper script MUST NOT be created via `hermes profile alias`** — that command writes a `hermes -p <profile>` wrapper that destroys the herdr behavior. Create wrappers manually (see `lab-landing-page-creator-claude` template).
|
|
- **Always use the workspace-relative path** in herdr `cwd` — relative paths break when herdr respawns in a different shell context.
|
|
- **The first `claude` message generates the session id** — `multi-agent-mux-create` only sets up the *container*. If you need a known session id for later resume, send a placeholder message (e.g. "init") and read it back, then call `multi-agent-mux-resume` later.
|
|
|
|
## Verification
|
|
|
|
After spawn + YAML append:
|
|
|
|
```bash
|
|
# 1. herdr session is alive (real native command — no lib.sh needed)
|
|
herdr agent get "$SESSION_NAME" >/dev/null 2>&1 && echo OK || echo MISSING
|
|
|
|
# 2. pane has the expected cmd + cwd
|
|
herdr agent get "$SESSION_NAME" | python3 -c "
|
|
import sys, json
|
|
a = json.load(sys.stdin)['result']['agent']
|
|
print(f\"cmd={a['agent']} cwd={a['cwd']}\")
|
|
"
|
|
|
|
# 3. agent-sessions.yaml has the new entry
|
|
python3 -c "
|
|
import yaml
|
|
d = yaml.safe_load(open('.mam/agent-sessions.yaml'))
|
|
names = [s['name'] for s in d['herdr_sessions']]
|
|
assert '$SESSION_NAME' in names, 'session not registered'
|
|
print('OK:', names)
|
|
"
|
|
|
|
# 4. Optional: check the TUI status (real native command)
|
|
herdr agent read "$SESSION_NAME" --source visible --lines 20 # TUI ready = agent banner visible, no dialog text
|
|
```
|
|
|
|
> `herdr has-session` / `herdr list-panes` / `herdr capture-pane` above are tmux-compat pseudo-commands only understood after `source .agents/skills/lib.sh` (see `Workflow`) — the real `herdr` binary has no such subcommands. The block above uses the real `herdr agent get`/`herdr agent read` equivalents so it also works standalone.
|
|
|
|
## When NOT to use this skill
|
|
|
|
- **Resuming an old conversation** → `multi-agent-mux-resume`
|
|
- **Killing an existing session** → `multi-agent-mux-stop`
|
|
- **Just attaching to an existing session** → `herdr agent attach <name>` (no skill needed)
|
|
- **One-shot print mode (claude -p "...")** → no herdr needed; use `claude-code` skill's print mode
|