# Orchestral

Workflow orchestration for grounded agents.

[中文版本](./README.zh-CN.md)

## What It Does

- Orchestrates stateful workflows, not one-off tool calls
- Executes typed actions with an `agent loop` and `mini-DAG`
- Replans from real state and verifies before finishing

## See It Work

One user command. Orchestral coordinates an MCP data source, a domain skill, and shell execution into a multi-step pipeline:

```
You:  "Query Q4 sales from the API, fill the Excel template with actuals
       and formulas, write a markdown summary comparing to budget."

Orchestral automatically:
  ├─ mcp__sales-api__query_sales_data  → fetch actuals from external API
  ├─ file_read budget.yaml             → load budget targets
  ├─ shell (venv python + openpyxl)    → fill Excel: values, formulas, status
  └─ file_write report.md              → generate comparison report
```

The planner discovers MCP tools at startup via `tool_lookup`, activates the `xlsx` skill for openpyxl guidance, and uses the skill's virtual environment to run Python. When a step fails, the agent loop observes the error and replans — no manual intervention needed.

**Try it:**

```bash
export OPENROUTER_API_KEY="sk-or-..."
cargo build -p orchestral-cli
cargo run -p orchestral-cli -- scenario \
  --spec configs/scenarios/sales_report_pipeline.smoke.yaml
```

## Architecture

```
Intent → Planner (LLM) → Normalizer (DAG validation) → Executor (parallel + retry)
            ↑                                                    ↓
            └──── agent loop: observe execution result ──────────┘
```

- **Agent loop** — planner iterates up to 6 rounds, observing results and replanning
- **MCP integration** — servers probed at startup, each tool registered as a callable action with deferred schema loading via `tool_lookup`
- **Skills** — domain knowledge (SKILL.md files) auto-discovered and injected into planner context; `skill_activate` for on-demand loading
- **Typed actions** — document inspect/patch/verify, structured config patch/verify, shell, file I/O, HTTP

## SDK

Use Orchestral as a library — register custom actions and lifecycle hooks with a builder API:

```rust
use orchestral::{Orchestral, core::action::*};

let app = Orchestral::builder()
    .action(MyCustomAction::new())
    .hook(MyLoggingHook::new())
    .planner_backend("openrouter")
    .planner_model("anthropic/claude-sonnet-4.5")
    .build()
    .await?;

let result = app.run("Analyze the data and generate a report").await?;
println!("{}", result.message);
```

See [`examples/sdk_quickstart.rs`](examples/sdk_quickstart.rs) and [`examples/sdk_hooks.rs`](examples/sdk_hooks.rs).

## Install

```bash
# As a library
cargo add orchestral

# As a CLI tool
cargo install orchestral-cli
```

## Quick Start

Export one provider key:

```bash
export GOOGLE_API_KEY="..."  # or OPENAI_API_KEY, ANTHROPIC_API_KEY, OPENROUTER_API_KEY
```

CLI:
```bash
orchestral-cli run
```

As a library:
```rust
let app = Orchestral::builder()
    .planner_backend("google")
    .planner_model("gemini-2.5-flash")
    .build().await?;
let result = app.run("read README.md").await?;
```

## Project Structure

```
core/orchestral-core     — Pure abstractions: Intent/Plan/Step, traits, DAG executor
core/orchestral-runtime  — LLM planners, actions, MCP bridge, skill system
core/orchestral          — Facade re-exporting core + runtime
apps/orchestral-cli      — CLI + TUI (ratatui)
apps/orchestral-telegram — Telegram bot adapter
```

## Telegram Bot

Run Orchestral as a Telegram bot — each message goes through the full orchestration pipeline:

```bash
export TELEGRAM_BOT_TOKEN="your-bot-token"
export GOOGLE_API_KEY="your-key"  # or OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.
cargo run -p orchestral-telegram
```

LLM backend is configurable in code (defaults to Google Gemini). The bot supports file operations, shell commands, and multi-turn conversations.

## Current Status

- Core orchestration loop working with agent loop + mini-DAG
- MCP per-tool registration with deferred schema loading
- Skill auto-discovery and on-demand activation
- SDK with builder API, lifecycle hooks, and programmatic execution
- Telegram bot adapter (configurable LLM backend)
- Document and structured config typed pipelines
- Scenario smoke tests covering core workflows

## License

See [LICENSE](./LICENSE).
