Skip to content

feat(cli): multi-agent workspaces with @alias, expert.toml and expert use#3

Closed
feliperun wants to merge 1 commit into
mainfrom
feat/multi-agent-workspace
Closed

feat(cli): multi-agent workspaces with @alias, expert.toml and expert use#3
feliperun wants to merge 1 commit into
mainfrom
feat/multi-agent-workspace

Conversation

@feliperun
Copy link
Copy Markdown
Owner

Summary

Single-agent repos keep the same ergonomics; multi-agent repos get a first-class experience via three equivalent targeting syntaxes backed by a shared resolver.

# One-off shortcut
expert @ecg  ask "What does lead V1 tell us?"
expert @derm ask "Differential for an acral nodule?"

# Explicit flag (CI-friendly)
expert ask --agent ecg "..."

# Pin for this shell / workspace (stored in .expert/state.json)
expert use ecg
expert ask "..."

What's new

Area Change
Commands expert agents, expert use <name> / --clear, expert which [--agent ...]
Flag --agent/-a <name> on ask, validate, count-tokens, sync, test, sessions {list,show,delete}, which
Shortcut @alias positional — expert @ecg ask "..." rewritten to expert ask "..." --agent ecg before Typer parses
Config expert.toml at repo root: [defaults] + one [agents.<name>] section per agent (schema path, endpoint, api_key_env, description)
Discovery Walk up for expert.toml / .expert/state.json; fall back to sibling */agent_schema.yaml rooted at cwd
CI Reusable workflow gains optional agent: input so monorepos can matrix over agents
Docs README gets a "Multi-agent workspaces" section; AGENT_E2E_SETUP.md grows a monorepo matrix snippet

Resolution precedence (first match wins)

  1. --schema <path> short-circuits to that file (preserves legacy behaviour)
  2. --agent <name> / @alias (explicit selector)
  3. EXPERT_AGENT env var
  4. .expert/state.json (set by expert use)
  5. [defaults] agent = "..." in expert.toml
  6. Exactly-one-agent short-circuit

Ambiguity raises AmbiguousAgentError with a helpful multi-line message listing every candidate and the three ways to pick one.

Architecture

cli/expert/
├── workspace.py      # Workspace.discover(), AgentContext, AgentInfo, errors
├── context.py        # single resolve() helper — every command routes through it
├── main.py           # argv rewriter with _AGENT_AWARE allow-list
└── commands/
    ├── agents.py     # new: agents / use / which
    ├── ask.py        # + --agent, uses resolve_context
    ├── validate.py   # + --agent
    ├── count_tokens.py  # + --agent
    ├── sync.py       # + --agent + kept --endpoint/--api-key as overrides
    ├── test.py       # + --agent; propagates to EXPERT_AGENT_* env for Robot
    ├── sessions.py   # + --agent on list/show/delete
    └── init.py       # hints "multi-agent detected" when scaffolding inside a workspace

Tests

  • 20 unit tests in cli/tests/test_workspace.py covering every precedence rule, prefix matching (unique / ambiguous / unknown), TOML + sibling coexistence, API-key resolution via api_key_env, require_remote() guard, state-file round-trip.
  • 14 tests in cli/tests/test_main_alias.py for the argv rewriter (agent-aware allow-list, sub-Typer end-append, empty-alias no-ops) plus CLI integration of agents / use / which via CliRunner.
  • All 85 tests (CLI + backend) green, ruff check clean, mypy clean on backend/app + cli/expert.

Backward compatibility

  • Existing single-agent scripts (expert validate --schema ..., expert ask --endpoint ... --api-key ...) keep working — the --schema flag short-circuits the resolver and CLI flags continue to override env/config.
  • The micromed-agents workflow (e2e-ecg-expert.yml) needs no changes; it's already single-agent.

Test plan

  • python -m pytest cli/tests backend/tests → 85 passed
  • ruff check + ruff format --check clean
  • mypy backend/app cli/expert clean
  • Local smoke: expert agents, expert use, expert which, expert @alias ask, ambiguous workspace error message
  • CI run on the PR
  • Manual verification against a deployed agent: expert @ecg-expert ask "..." in micromed-agents

Follow-ups (not in this PR)

  • Tab-completion for agent names (Typer supports shell_complete=)
  • expert register <name> --schema <path> to update expert.toml non-destructively
  • Surface the active agent in the ask streaming UI ("→ ecg · session xxx")

Made with Cursor

…expert use`

Single-agent repos keep their existing ergonomics; multi-agent repos get a
first-class experience via three equivalent targeting syntaxes and a shared
resolver so every command picks up precedence rules automatically.

## New surface

- `expert agents` — list every agent (TOML-declared + auto-discovered siblings)
- `expert use <name>` — pin an agent in `.expert/state.json` for this workspace
- `expert which [--agent ...]` — preview what a bare command would resolve to
- `@alias` positional shortcut: `expert @derm ask "..."` → same as `expert ask --agent derm "..."`
- `--agent/-a <name>` flag on `ask`, `validate`, `count-tokens`, `sync`, `test`,
  `sessions list|show|delete`, plus `which` for previewing resolution
- `expert.toml` at the workspace root with `[defaults]` + `[agents.<name>]`
  sections (schema path, endpoint, api_key_env, description)

## Resolution precedence (first match wins)

1. `--schema <path>` short-circuits to that file (preserves legacy behaviour)
2. `--agent <name>` / `@alias` (explicit selector)
3. `EXPERT_AGENT` env var
4. `.expert/state.json` (set by `expert use`)
5. `[defaults] agent = "..."` in `expert.toml`
6. Exactly-one-agent short-circuit

Failing to disambiguate raises `AmbiguousAgentError` with a helpful message
listing every candidate and the three ways to pick one.

## Architecture

- `cli/expert/workspace.py`: `Workspace.discover()`, `AgentContext`,
  `AgentInfo`, `AmbiguousAgentError`. Walks up for `expert.toml` or
  `.expert/state.json`; falls back to sibling-schema discovery rooted at cwd.
- `cli/expert/context.py`: single `resolve()` helper called by every command,
  so changing precedence rules in the future is a one-file edit.
- `cli/expert/main.py`: argv rewriter that expands `@alias` before Typer
  parses, with an allow-list of agent-aware subcommands so nonsense like
  `expert @foo use bar` is left alone for Typer's error renderer.

## Docs & CI

- Reusable workflow (`.github/workflows/expert-e2e.yml`) gains an `agent:`
  input so monorepos can run `expert test --agent X` via matrix.
- README grows a "Multi-agent workspaces" section with `expert.toml` sample.
- `docs/AGENT_E2E_SETUP.md` gains a matrix snippet for monorepo integrations.

## Tests

- 20 new unit tests for `workspace.py` covering every precedence rule, prefix
  matching, state file round-trips, and API-key env resolution.
- 14 new tests for the argv rewriter + CLI integration of `agents`/`use`/`which`.
- All 85 existing + new tests green; ruff + mypy clean.

Made-with: Cursor
@feliperun
Copy link
Copy Markdown
Owner Author

Superseded: the commit on this branch is already in main via #4 (see commit 33da587 included in the squash-merge a35a034).

@feliperun feliperun closed this Apr 17, 2026
@feliperun feliperun deleted the feat/multi-agent-workspace branch April 17, 2026 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant