Quickstart Crew CLI

View as Markdown

The smallestai agent-crew CLI is built for rapid iteration. Test your crew locally with a single command, then deploy to the cloud when ready. No configuration files, no Docker, no infrastructure management.

Local-first development: Run and test your agent entirely on your machine. Deploy only when you’re satisfied.

Building in the dashboard instead, or want the design model for an agent (which settings to configure, in what order, and why)? See Build your agent. This quickstart is the code path; that guide is the platform path.


Installation

The CLI comes bundled with the SDK:

$pip install smallestai

Verify the installation:

$smallestai --help

You’ll need a Smallest API key (from app.smallest.ai/dashboard/api-keys) for the CLI and SDK helpers. Export it:

$export SMALLEST_API_KEY=sk_...

Plus an LLM for the example below. The Atoms Crews SDK ships an OpenAIClient that accepts any OpenAI-compatible endpoint - pick one:

Smallest’s voice-optimized SLM. Reuses SMALLEST_API_KEY - no separate LLM key required.

1from smallestai.atoms.crew.clients.openai import OpenAIClient
2import os
3
4llm = OpenAIClient(
5 model="electron",
6 api_key=os.getenv("SMALLEST_API_KEY"),
7 base_url="https://api.smallest.ai/waves/v1",
8)

The Atoms Crews OpenAIClient is async - call sites use await llm.chat(messages=[...]) inside a crew node’s generate_response() method (which already runs in an event loop). It does not expose the OpenAI-Python-SDK shape llm.chat.completions.create(...); the call surface is await llm.chat(messages, stream=False, tools=None, ...) returning a ChatResponse with .content and .tool_calls.

Test connectivity outside a crew

For a one-off sanity check (verify your key works, the endpoint responds), use the standard openai Python SDK - Electron is OpenAI-compatible, so the official client works as a drop-in by overriding base_url:

1import os
2from openai import OpenAI
3
4client = OpenAI(
5 api_key=os.environ["SMALLEST_API_KEY"],
6 base_url="https://api.smallest.ai/waves/v1",
7)
8
9resp = client.chat.completions.create(
10 model="electron",
11 messages=[{"role": "user", "content": "Respond with a one-sentence greeting."}],
12 max_tokens=50,
13)
14print(resp.choices[0].message.content)

Same code works against OpenAI itself by dropping base_url and swapping model to gpt-4o-mini (and using OPENAI_API_KEY). Use this pattern for backend scripts or smoke tests that aren’t inside a crew node.


Create Your First Agent Crew

Before the CLI has anything to connect to, you need a Python file that defines a crew and starts a WebSocket server. Pick one of the two patterns below and pull the example folder straight from the cookbook - the tar command drops a getting_started/ or background_agent/ directory into your cwd, ready to cd into. For local development, no .env is needed - the examples read SMALLEST_API_KEY (and optionally OPENAI_API_KEY) straight from your shell. For cloud deployment, you’ll need a .env file (see the Ship env vars in a .env step further down). Each folder ships a one-line requirements.txt pinning smallestai, which the cloud build also uses when you deploy.

Single-node crew

A minimal, single-node crew that streams chat completions from an LLM and greets the caller on join - copied from the cookbook’s getting_started.

$curl -sL https://github.com/smallest-inc/cookbook/archive/refs/heads/main.tar.gz \
> | tar -xz --strip-components=2 cookbook-main/voice-agents/getting_started
$cd getting_started
$pip install -r requirements.txt

server.py is the entry point - it boots an AtomsCrewApp on ws://localhost:8080/ws. assistant.py contains the OutputCrewNode subclass that streams the LLM response; extend it with your own prompt, tools, and logic.

Project layout: a flat directory (server.py + requirements.txt at the root, like the cookbook examples) is the simplest and best-tested shape. A src/ layout with a pyproject.toml also builds and deploys; if you go that route, declare every runtime dependency in the pyproject.toml.

Multi-node crew with background processing

A two-node example from background_agent - a support agent talking to the user, and a sentiment analyzer running silently in parallel that flags frustration and triggers auto-escalation.

$curl -sL https://github.com/smallest-inc/cookbook/archive/refs/heads/main.tar.gz \
> | tar -xz --strip-components=2 cookbook-main/voice-agents/background_agent
$cd background_agent
$pip install -r requirements.txt

app.py wires both nodes into a single CrewSession. support_agent.py is the user-facing OutputCrewNode; it can query the sibling sentiment node mid-conversation. sentiment_analyzer.py is a BackgroundCrewNode - it listens to every transcript event, classifies sentiment, and updates state the support agent reads.

What you’re working with:

  • OutputCrewNode - base class for nodes that produce user-facing output. Override generate_response() to define what the agent says.
  • BackgroundCrewNode - base class for nodes that observe events silently. Override process_event() to react. No audio output, no interrupts.
  • CrewSession - the runtime that owns the WebSocket connection and runs your nodes in parallel for each call.
  • AtomsCrewApp - the FastAPI WebSocket server that the CLI’s chat command, and the production Atoms orchestrator, connect to.

Local Development Workflow

The CLI’s best feature is instant local testing. No need to deploy to test changes.

1

Start Your Agent Server

Run the entry point to start a local WebSocket server:

$python server.py

This spins up a server on localhost:8080 that mimics the production environment.

2

Connect via CLI

In another terminal, start an interactive voice session:

$smallestai agent-crew chat

The CLI connects to your local server and lets you converse with your agent in real-time.

CLI Chat

3

Iterate Rapidly

Make code changes, restart the server, and reconnect with chat. No redeploys needed.


Cloud Deployment

When you’re ready for production, deploy to Smallest AI’s managed infrastructure.

Prerequisite: You need an existing agent on the Atoms platform - agent-crew init links your local code to it. Create one from the dashboard, or programmatically via the SDK:

1from smallestai import SmallestAI
2
3# Reads SMALLEST_API_KEY from the environment, or pass api_key="sk_..." explicitly.
4client = SmallestAI()
5response = client.atoms.agents.create_agent(name="my-test-agent")
6agent_id = response.data # the agent id is a string at .data
7print(agent_id)
1

Authenticate

$smallestai auth login

Prompts for your Smallest API key (paste it from app.smallest.ai/dashboard/api-keys). The key is stored at ~/.smallestai/credentials.json with 0600 permissions.

Already have SMALLEST_API_KEY exported? Pipe it in:

$echo $SMALLEST_API_KEY | smallestai auth login
3

Ship env vars in a .env (required)

Platform-side secrets injection isn’t built yet. The deploy zip does not carry your shell environment.

How .env works on the cloud: the zip ships every file in your dir except __pycache__/, .venv/, etc. - .env is not excluded. The cookbook’s assistant.py calls load_dotenv() at import time, so on the cloud it reads .env from the same directory. Keys defined locally end up available to os.getenv(...) in the cloud agent.

Create one next to server.py:

$cat > .env <<EOF
$OPENAI_API_KEY=$OPENAI_API_KEY
$SMALLEST_API_KEY=$SMALLEST_API_KEY
$EOF
4

Deploy

$smallestai agent-crew deploy --entry-point server.py

Packages your code and pushes it to the cloud. Takes about 30 seconds.

5

Go Live

A successful deploy is not live by default. Builds land in SUCCEEDED with isLive: null - your agent will not answer calls until you promote one.

$smallestai agent-crew builds

Select your build and choose Make Live to start serving traffic.

No TTY? The builds command needs an interactive terminal. Promote via REST:

$curl -X PATCH "https://api.smallest.ai/atoms/v1/sdk/agents/$AGENT_ID/builds/$BUILD_ID" \
> -H "Authorization: Bearer $SMALLEST_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{"isLive": true}'

Command Reference

Authentication

CommandDescription
smallestai auth loginPrompts for your Smallest API key and stores it at ~/.smallestai/credentials.json. Accepts the key piped on stdin.
smallestai auth logoutClear stored credentials

Agent Management

CommandDescription
smallestai agent-crew initLink local directory to a platform agent
smallestai agent-crew deployDeploy code to the cloud
smallestai agent-crew buildsView and manage deployments
smallestai agent-crew chatStart interactive session with local agent

Common Options

OptionDescription
--entry-point <file>Specify the main Python file (default: server.py)
--helpShow help for any command

Build Management

Deployments are not live by default. This gives you a safety buffer.

One Live Build Per Agent: Making a new build live automatically takes down the previous one.

To promote a build:

  1. Run smallestai agent-crew builds
  2. Select the desired build
  3. Choose Make Live

To roll back:

  1. Run smallestai agent-crew builds
  2. Select the previous build
  3. Choose Make Live

To take down completely:

  1. Run smallestai agent-crew builds
  2. Select the LIVE build
  3. Choose Take Down

Running the CLI in CI / non-interactive environments

A few commands prompt you for input (an agent picker, a build picker, a password field). These only work in a real terminal. The table below shows which commands work non-interactively and how to substitute for the ones that don’t.

CommandWorks in CI?Notes
smallestai auth loginYesPipe the key on stdin: echo "$SMALLEST_API_KEY" | smallestai auth login.
smallestai agent-crew initNoOpens an interactive picker over your agents. In CI, write the config directly instead - see below.
smallestai agent-crew deployYesFully non-interactive. Reads agent_id from .smallestai/config.toml, the API key from stored credentials, prints a deploy summary, and exits non-zero on failure.
smallestai agent-crew buildsNoLists builds, then prompts you to pick one and choose Make Live / Take Down. For CI promotion or rollback, call the API directly - see below.
smallestai agent-crew chatNoInteractive WebSocket REPL against ws://localhost:8080/ws. For local development only.

Skipping init in CI

init exists to write .smallestai/config.toml with your agent ID. In CI you can write the same file yourself before running deploy:

$mkdir -p .smallestai
$cat > .smallestai/config.toml <<EOF
$agent_id = "$ATOMS_AGENT_ID"
$EOF

Promoting and rolling back builds in CI

builds calls the same endpoint for both Make Live and Take Down. You can call it directly:

$# Promote a build (Make Live)
$curl -X PATCH "https://api.smallest.ai/atoms/v1/sdk/agents/$ATOMS_AGENT_ID/builds/$BUILD_ID" \
> -H "Authorization: Bearer $SMALLEST_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{"isLive": true}'
$
$# Roll back (Take Down)
$curl -X PATCH "https://api.smallest.ai/atoms/v1/sdk/agents/$ATOMS_AGENT_ID/builds/$BUILD_ID" \
> -H "Authorization: Bearer $SMALLEST_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{"isLive": false}'

The build ID is printed by deploy on success, and is also available from GET /atoms/v1/sdk/agents/{agentId}/builds.

Only one build per agent can be live at a time. Setting isLive: true on a new build automatically takes down the previously-live one.


Error handling

When deployed code raises, the SDK auto-records the error on the call (in calllog.errors[], the Events tab, and webhooks) - you don’t need to wire anything up to get this. The deploy command also warns about env vars your code references before zip upload, and the pod’s /ready endpoint blocks traffic until your crew’s __init__ succeeds. See Error Handling for severity semantics, graceful-fallback patterns, and how to emit your own application-level errors.


FAQ

Your crew node owns the LLM turn only: it receives the transcript as messages and yields text. Speech-to-text (Pulse / Pulse Pro) and text-to-speech (Lightning) are set on the agent in the dashboard, not in code, and run platform-side. Turn-taking, interrupts, and telephony are platform-side too. So the pipeline is:

caller audio -> Smallest STT -> your crew node (your LLM) -> text -> Smallest TTS -> caller

You never write STT or TTS code. You pick them in agent settings; your node just generates the words.

Yes, and it is the default, not a special mode. OpenAIClient accepts any OpenAI-compatible endpoint via base_url. Point it at your runtime:

1self.llm = OpenAIClient(
2 model="your-model",
3 api_key=os.getenv("YOUR_LLM_KEY"),
4 base_url="https://your-runtime.example.com/v1",
5)

It needs the Chat Completions shape (/v1/chat/completions), streaming, and tool-calling if you use tools. Not OpenAI-shaped? Put a thin proxy in front. Nothing else changes: you still get Smallest STT and TTS on the same agent.

Multi-agent is supported. A CrewSession runs multiple nodes in parallel for one call:

  • OutputCrewNode: user-facing, produces speech. You can have more than one (for example a router that hands off).
  • BackgroundCrewNode: observes every event silently (no audio), for example live sentiment, compliance checks, or logging. Output nodes can read a background node’s state mid-call.

The background_agent example shows a support agent plus a sentiment analyzer that triggers auto-escalation. Start single-node (getting_started), add nodes as you need them.

Yes. Run python server.py, then smallestai agent-crew chat in a second terminal for a text REPL against your local crew: real session lifecycle, your real LLM, no telephony. Iterate there, then deploy.

Platform-level env injection isn’t available yet. The working path is to keep a .env file at your project root and load it at startup:

1# server.py (or wherever your entry point is)
2from dotenv import load_dotenv
3load_dotenv()

The .env ships in the deploy bundle and is loaded in the pod, so os.getenv(...) finds your variables in the cloud the same way it does locally. The cookbook examples all follow this pattern.

The env-var warning printed by smallestai agent-crew deploy is a reminder to populate .env before uploading. It doesn’t block the deploy.

Flat directory. Entry file (server.py) and requirements.txt at the root, with node files alongside:

my-crew/
├── server.py
├── assistant.py
├── requirements.txt
└── .env

A src/ layout will not work. The cloud build copies your pyproject.toml and runs pip install . before it copies the rest of your source, so with a src/ layout the package isn’t on disk yet. The install fails and the build stops (visible as a deploy stuck in QUEUED).

Two ways to avoid this:

  • Flat layout (recommended). Keep server.py + node files at the root, as above.
  • Add a requirements.txt if you want to keep a pyproject.toml for local tooling or editable installs. When both are present the builder uses requirements.txt and skips pip install . entirely.

More examples

The two crews above are the starting points. The Smallest AI cookbook ships ~15 ready-to-run voice-agent examples covering tool calling, call control, multi-language support, knowledge-base grounding, real banking / scheduling / IVR flows, observability, and more - each in its own directory with the same curl-and-run shape.

Need Help?