Push Tracker
ria-toolkit-oss/screens_connection_updates.md

5.6 KiB

Agent CLI Simplification — Handoff to ria-toolkit-oss

Repo: ria-toolkit-oss, branch screens-connection Goal: Reduce agent setup from 3+ commands to 2 simple ones.


Current UX (painful)

# Step 1: Register via curl against FastAPI directly
curl -X POST http://hub:8005/screens/agents/register \
  -H 'X-API-Key: supersecretapikey' \
  -d '{"name": "my-agent"}'
# → {"agent_id": "agent-55cf3c5b8137f6f3", "token": "45Hbt..."}

# Step 2: Manually save credentials
ria-agent register \
  --url http://hub:8005 \
  --token 45HbtlpVDX7_XTF47biDcLcyiVmM51icEZVJ7J_UrEE \
  --agent-id agent-55cf3c5b8137f6f3

# Step 3: Stream (with manual URL construction)
ria-agent stream \
  --url "ws://hub:8005/screens/agent/ws?agent_id=agent-55cf3c5b8137f6f3" \
  --token 45HbtlpVDX7_XTF47biDcLcyiVmM51icEZVJ7J_UrEE

Problems:

  • User must know the FastAPI port (8005), not just the hub URL (3005)
  • register subcommand only saves locally — doesn't call the server
  • _derive_ws_url builds /api/agent/ws/{agent_id} but server endpoint is /screens/agent/ws?agent_id=...
  • User must copy-paste agent_id and token between commands

Target UX

# One-time setup: register with the hub (hits server, saves config)
ria-agent register --hub http://whitehorse:3005 --api-key supersecretapikey --name lab-pluto

# Stream (reads config, connects automatically)
ria-agent stream

That's it. Two commands, no copy-pasting.


Changes needed in ria-toolkit-oss

1. cli.py — Make register call the server

Current _cmd_register just saves to ~/.ria/agent.json. It should:

  1. POST to {hub_url}/screens/agents/register with X-API-Key header
  2. Receive {agent_id, token} from the server
  3. Save everything to ~/.ria/agent.json
def _cmd_register(args: argparse.Namespace) -> int:
    import urllib.request
    import json as _json

    hub_url = args.hub.rstrip("/")
    api_key = args.api_key

    # Call the server to register
    url = f"{hub_url}/screens/agents/register"
    body = _json.dumps({"name": args.name or ""}).encode()
    req = urllib.request.Request(
        url,
        data=body,
        headers={
            "Content-Type": "application/json",
            "X-API-Key": api_key,
        },
    )
    try:
        with urllib.request.urlopen(req) as resp:
            data = _json.loads(resp.read())
    except Exception as e:
        print(f"error: registration failed: {e}", file=sys.stderr)
        return 1

    agent_id = data["agent_id"]
    token = data["token"]

    # Save to config
    cfg = _config.load()
    cfg.hub_url = hub_url
    cfg.agent_id = agent_id
    cfg.token = token
    if args.name:
        cfg.name = args.name
    cfg.insecure = bool(args.insecure)
    path = _config.save(cfg)

    print(f"Registered agent: {agent_id}")
    print(f"Credentials saved to {path}")
    return 0

Update the argparse for register:

p_reg = sub.add_parser("register", help="Register agent with RIA Hub and save credentials")
p_reg.add_argument("--hub", required=True, help="RIA Hub URL (e.g. http://whitehorse:3005)")
p_reg.add_argument("--api-key", required=True, help="Hub API key for authentication")
p_reg.add_argument("--name", default=None, help="Human-friendly agent name")
p_reg.add_argument("--insecure", action="store_true", help="Skip TLS verification")

Remove --url, --token, --agent-id from register — those are now server-generated.

2. cli.py — Fix _derive_ws_url

Current (wrong):

suffix = f"/api/agent/ws/{agent_id}" if agent_id else "/api/agent/ws"

Should be:

suffix = f"/screens/agent/ws?agent_id={agent_id}" if agent_id else "/screens/agent/ws"

3. cli.py — Make stream zero-arg by default

Current _cmd_stream already loads config and derives the URL — it just needs the URL fix above. After that, bare ria-agent stream works if register was run first.

4. config.py — Add api_key field (optional)

Add api_key: str = "" to AgentConfig so the hub API key can be persisted for re-registration or other API calls. Not strictly required but useful.


Changes already done in ria-hub (Part B)

The server side is ready:

  • POST /screens/agents/register — accepts {"name": "..."} with X-API-Key header, returns {"agent_id": "...", "token": "..."}
  • GET /screens/agent/ws?agent_id=... — WebSocket endpoint, authenticates via Authorization: Bearer {token} header
  • Agent token is hashed (SHA-256) and stored in MongoDB; lookup happens on WS connect

The Go proxy for /screens/agents/register through port 3005 still needs to be added (currently agents must hit FastAPI port 8005 directly). That's a ria-hub task, not ria-toolkit-oss.


Summary of file changes

File Change
src/ria_toolkit_oss/agent/cli.py register calls server API, new flags --hub/--api-key; fix _derive_ws_url path
src/ria_toolkit_oss/agent/config.py Optional: add api_key field to AgentConfig
tests/agent/test_cli.py Update register tests for new server-calling behavior

Validated E2E flow (what works today)

We tested the full pipeline on whitehorse with a real Pluto SDR:

  1. Agent connects via WebSocket with bearer token auth
  2. Server sends start with radio_config via Redis pub/sub → agent
  3. Agent opens Pluto, streams interleaved float32 IQ via binary WS frames
  4. FastAPI pushes frames to Redis list, Celery worker's AgentDataSource.next_chunk() BLPOP reads them
  5. Inference loop runs on live agent data identically to direct SDR mode

The only manual friction is the multi-step registration and URL construction — which these CLI changes eliminate.