# Two Console Demo
This is the simplest end-to-end local demo using two terminals:
- terminal 1 as `agent1`
- terminal 2 as `agent2`
It uses the tools that already exist in this repo:
- `rho`
- `rho-chat`
- `rho-dataset`
- `publish`
It does not yet use the future automated message bus or approval daemon.
Where those pieces do not exist yet, this walkthrough uses explicit manual files.
This demo now uses a dedicated sandbox root:
```text
./sandbox/two-console-demo/
```
That means the demo writes its generated `users/`, `shared/`, request, and result files under `./sandbox/two-console-demo/`, so you can inspect or delete the whole tree in one step.
## What You Will Prove
By the end of this demo:
- `agent1` and `agent2` run in separate `pi` sessions
- `agent1` stages a twin dataset with mock and real variants
- `agent1` publishes only the mock twin into shared space
- `agent2` writes code against the shared mock dataset
- `agent2` tests that code locally
- `agent2` manually requests a real-data run from `agent1`
- `agent1` reviews the code and runs it against the private real data
- `agent1` publishes the result back into the shared folder
- `agent2` reads the published result
## Prerequisites
From the repo root:
```bash
cd /Users/madhavajay/dev/rho/main
```
You should already have:
- `pi` installed and built
- `user1` authenticated in `pi`
- `user2` authenticated in `pi`
Useful check:
```bash
./rho user1 "Say exactly: user1 harness is working"
./rho user2 "Say exactly: user2 harness is working"
```
## Terminal 1: Agent1
Start the interactive `pi` session:
```bash
cd /Users/madhavajay/dev/rho/main
./rho-chat user1
```
Leave it open.
## Terminal 2: Agent2
Start the second interactive `pi` session:
```bash
cd /Users/madhavajay/dev/rho/main
./rho-chat user2
```
Leave it open.
## Terminal 3: Setup Commands
Use a third shell for filesystem setup and manual request/result files.
```bash
cd /Users/madhavajay/dev/rho/main
mkdir -p ./sandbox/two-console-demo
```
## Step 1: Agent1 Creates The Twin Dataset
Run:
```bash
./rho-dataset \
--name prices-demo \
--real ./examples/datasets/prices-real.csv \
--mock ./examples/datasets/prices-mock.csv \
--owner user1 \
--share-dir ./sandbox/two-console-demo/users/user1/datasets/share \
--private-dir ./sandbox/two-console-demo/users/user1/datasets/private \
--description "Example price dataset with real and mock CSV twins"
```
This stages the dataset under:
```text
./sandbox/two-console-demo/users/user1/datasets/share/<uuid>/
./sandbox/two-console-demo/users/user1/datasets/private/<uuid>/
```
If you want to inspect it:
```bash
## Step 2: Agent1 Publishes The Mock Twin
Use the dataset UUID printed by the previous command.
Example:
```bash
./publish user1 fec0edc4-007a-4437-993e-0cd17fe4df55 \
--source-root ./sandbox/two-console-demo/users \
--target-root ./sandbox/two-console-demo/shared/datasets
```
This copies the shareable bundle into:
```text
./sandbox/two-console-demo/shared/datasets/<uuid>/
```
Verify:
```bash
For the example UUID:
```bash
## Step 3: Agent2 Inspects The Shared Dataset
In terminal 2 (`agent2`), ask:
```text
Read sandbox/two-console-demo/shared/datasets/fec0edc4-007a-4437-993e-0cd17fe4df55/dataset.yaml and sandbox/two-console-demo/shared/datasets/fec0edc4-007a-4437-993e-0cd17fe4df55/mock/prices-mock.csv. Explain the schema and tell me how to sum the price column.
```
## Step 4: Agent2 Writes The Code
Still in terminal 2, ask:
```text
Create sandbox/two-console-demo/shared/workspace/sum_prices.py that reads a CSV with columns date,symbol,price and prints the sum of the price column.
```
If the directory does not exist yet, ask it to create it or create it manually:
```bash
mkdir -p ./sandbox/two-console-demo/shared/workspace
```
## Step 5: Agent2 Tests Against Mock Data
In terminal 2, ask:
```text
Run python3 sandbox/two-console-demo/shared/workspace/sum_prices.py sandbox/two-console-demo/shared/datasets/fec0edc4-007a-4437-993e-0cd17fe4df55/mock/prices-mock.csv
```
This is the current stand-in for the future sandboxed mock-run tool.
## Step 6: Agent2 Creates A Real-Run Request
The request tooling is not built yet, so create the request manually from terminal 3:
```bash
mkdir -p sandbox/two-console-demo/shared/.rho/requests
mkdir -p sandbox/two-console-demo/shared/.rho/inbox/agent1
```
Create the request manifest:
```bash
cat > sandbox/two-console-demo/shared/.rho/requests/req-001.yaml <<'EOF'
version: 1
request:
id: req-001
from: agent2
to: agent1
dataset_uuid: fec0edc4-007a-4437-993e-0cd17fe4df55
code_paths:
- sandbox/two-console-demo/shared/workspace/sum_prices.py
command:
- python3
- sandbox/two-console-demo/shared/workspace/sum_prices.py
- DATASET_CSV
requested_tier: real
created_at: 2026-04-02T00:00:00Z
EOF
```
Create the inbox message for `agent1`:
```bash
cat > sandbox/two-console-demo/shared/.rho/inbox/agent1/msg-001.yaml <<'EOF'
version: 1
message:
id: msg-001
from: agent2
to: agent1
type: request_run_real
related_request_id: req-001
body:
text: "Please review and run req-001 on the real dataset."
EOF
```
## Step 7: Agent1 Reviews The Incoming Request
In terminal 1 (`agent1`), ask:
```text
Read sandbox/two-console-demo/shared/.rho/inbox/agent1/msg-001.yaml and sandbox/two-console-demo/shared/.rho/requests/req-001.yaml, then review sandbox/two-console-demo/shared/workspace/sum_prices.py and summarize what it does and whether it looks safe.
```
This is the current manual version of the future `review_shared_code` tool.
## Step 8: Agent1 Runs On Mock First
From terminal 3:
```bash
python3 sandbox/two-console-demo/shared/workspace/sum_prices.py sandbox/two-console-demo/shared/datasets/fec0edc4-007a-4437-993e-0cd17fe4df55/mock/prices-mock.csv
```
If you want to notify `agent2`, write a manual status update:
```bash
mkdir -p sandbox/two-console-demo/shared/.rho/inbox/agent2
cat > sandbox/two-console-demo/shared/.rho/inbox/agent2/msg-002.yaml <<'EOF'
version: 1
message:
id: msg-002
from: agent1
to: agent2
type: status_update
related_request_id: req-001
body:
status: mock_run_finished
text: "Mock run completed successfully."
EOF
```
## Step 9: Agent1 Runs On Real Data
The real/private CSV is local to `agent1` and was staged under:
```text
./sandbox/two-console-demo/users/user1/datasets/private/<uuid>/real/prices-real.csv
```
For the example UUID:
```bash
python3 sandbox/two-console-demo/shared/workspace/sum_prices.py sandbox/two-console-demo/users/user1/datasets/private/fec0edc4-007a-4437-993e-0cd17fe4df55/real/prices-real.csv
```
This is the current stand-in for the future Gondolin real-data run.
## Step 10: Agent1 Publishes The Result
From terminal 3:
```bash
mkdir -p sandbox/two-console-demo/shared/.rho/results
mkdir -p sandbox/two-console-demo/shared/results/req-001
```
Write the released output:
```bash
python3 sandbox/two-console-demo/shared/workspace/sum_prices.py sandbox/two-console-demo/users/user1/datasets/private/fec0edc4-007a-4437-993e-0cd17fe4df55/real/prices-real.csv > sandbox/two-console-demo/shared/results/req-001/output.txt
```
Write the result manifest:
```bash
cat > sandbox/two-console-demo/shared/.rho/results/req-001.yaml <<'EOF'
version: 1
result:
id: result-001
request_id: req-001
from: agent1
to: agent2
status: released
artifact_paths:
- sandbox/two-console-demo/shared/results/req-001/output.txt
EOF
```
Notify `agent2`:
```bash
cat > sandbox/two-console-demo/shared/.rho/inbox/agent2/msg-003.yaml <<'EOF'
version: 1
message:
id: msg-003
from: agent1
to: agent2
type: result_available
related_request_id: req-001
body:
text: "Result released for req-001."
result_manifest: "sandbox/two-console-demo/shared/.rho/results/req-001.yaml"
EOF
```
## Step 11: Agent2 Reads The Result
In terminal 2 (`agent2`), ask:
```text
Read sandbox/two-console-demo/shared/.rho/inbox/agent2/msg-003.yaml, sandbox/two-console-demo/shared/.rho/results/req-001.yaml, and sandbox/two-console-demo/shared/results/req-001/output.txt and summarize the released result.
```
## What Is Automated Today
Today’s automation:
- separate `pi` state per user
- twin dataset creation
- publish mock dataset to shared space
- shared mock development flow
## What Is Still Manual
Still manual in this walkthrough:
- request creation
- inbox message creation
- status update messages
- result manifest creation
- mock/real execution approval
- Gondolin sandbox orchestration
## Automated Check
There is also a repeatable smoke test for the current manual flow:
```bash
./tests/test-two-console-demo.sh
```
It does not launch the `pi` TUI.
Instead it automates the filesystem and execution parts of this walkthrough inside `./sandbox/two-console-demo/`:
- create twin dataset
- publish mock dataset
- run the shared `sum_prices.py` example on mock
- create a manual real-run request
- check request status
- approve the request through `./rho approve`
- run on private real data
- publish the result
For a live approval path through Telegram, create `.env` from [.env.example](/Users/madhavajay/dev/rho/main/.env.example) and run:
```bash
./tests/test-two-console-demo.sh --live
```
The live mode:
- initializes a Telegram bot profile inside `./sandbox/two-console-demo/`
- sends a rich approval request summary with inline `Approve`, `Deny`, and `Show Details` buttons
- also accepts `/approve req-...`, `/deny req-...`, `/show req-...`, `/approve_last`, and `/deny_last`
- records that decision through the same `./rho approve` CLI used by the non-live test
The transport split is documented in [approval-middleware.md](/Users/madhavajay/dev/rho/main/docs/approval-middleware.md).
The agentized controlled-action scenario adds offline fixture replay:
```bash
./tests/test-two-console-demo-agent-approval.sh --reset
./tests/test-two-console-demo-agent-approval.sh --record-fixtures --reset
./tests/test-two-console-demo-agent-approval.sh --offline --reset
./tests/test-two-console-demo-agent-approval.sh --offline --middleware fixture --middleware-fixture tests/fixtures/two-console-demo-agent-approval/middleware/deny-release.yaml --reset
```
That lets you:
- run the full online Pi flow
- record Pi step outputs into `tests/fixtures/...`
- replay the same scenario offline without calling Pi
- swap Telegram out for deterministic fixture approvals in tests
## Next Tools To Build
The next commands worth implementing are:
- `rho-message`
Create a routed inbox message.
- `rho-request`
Create a computation request manifest and notify the other agent.
- `rho-result`
Publish a result manifest and notify the requester.
- `review_shared_code`
`pi` extension tool for code review summaries.
- `run_request_on_mock`
`pi` extension tool for local mock execution.
- `run_request_on_real`
`pi` extension tool for local real execution, approval-gated.