Skip to main content

Verb-first LLM interaction for the shell, with optional punctuation shortcuts.

Project description

Zeta

CI PyPI Python License

Zeta is a local, event-driven runtime for authored agents.

An authored agent is a Markdown file that declares which durable events it accepts, which tools it can use, what events it may return, and the prompt that should run when it is triggered. The runtime stores events, queue state, run attempts, tool calls, model calls, and prompt traces in project-local SQLite databases so agent behavior can be replayed and inspected.

Zeta is alpha software. The repository also contains Commas, a shell frontend that uses the same runtime for interactive ask, propose, do, trace, and history workflows.

Install

The Python package is published as commas; it installs both zeta and commas commands:

uv tool install commas
zeta --help

For local development:

uv sync --group dev
uv run zeta --help
uv run commas --help

Zeta needs Python 3.11+ and a model endpoint. By default, local runs use an OpenAI-compatible chat completions endpoint at:

http://127.0.0.1:8080/v1/chat/completions

Model Profiles

Model profiles live in ~/.zeta/models.toml:

[[models]]
name = "fast"
model = "qwen2.5-coder"
url = "http://127.0.0.1:8080/v1/chat/completions"
thinking = "none"
default = true

[[models]]
name = "deep"
model = "qwen3-coder"
url = "http://127.0.0.1:8081/v1/chat/completions"
thinking = "high"

At most one profile may set default = true. If no default exists, Zeta falls back to local-model at the default local URL. thinking may be "none", "minimal", "low", "medium", or "high".

A profile can also use the Codex Responses backend through local Codex CLI credentials:

[[models]]
name = "codex"
model = "gpt-5.5"
api = "codex-responses"
thinking = "high"

That sends prompts and any tool-read file contents to OpenAI's backend. Run codex login first so ~/.codex/auth.json exists.

The zeta run worker resolves its model from the project runtime session stored under .zeta/sessions/default. For authored agents, the usual choices are to set a default = true profile in models.toml or to set a per-agent model: override in the agent frontmatter.

The Commas shell frontend also uses these profiles, but its commas model use command selects a profile for the current shell session, not for a project worker:

commas model list
commas model use fast
commas model show
commas model clear

Project Layout

Zeta reads authored agents from a flat agents/ directory in the project root:

agents/
  release-manager.md
  support-triage.md
  connectors.yaml
  events/
    github.pr.opened.json
    release.summary.ready.json
  skills/
    code-review.md
    release-notes.md
  tools/

Only top-level agents/*.md files are interpreted as agents. Directories such as agents/events/, agents/skills/, and agents/tools/ are resources, not nested agents.

The filename stem is the agent slug. It must match [a-z0-9_-]+.

Defining Agents

Each agent file is Markdown with YAML frontmatter and a Jinja prompt body. The prompt body may reference one root variable, event; validation rejects other undeclared roots.

---
name: Slack Support
description: Replies to Slack support messages.
model:
  name: qwen3-coder
  url: http://127.0.0.1:8080/v1/chat/completions
accepts:
  - slack.message.received
returns:
  - slack.message.post
tools:
  - read
  - grep
skills:
  - code-review
schedules:
  - cron: "0 9 * * 1"
    timezone: Europe/Paris
ingress:
  - event: slack.message.received
    filter:
      channel_ids: ["C123"]
    idempotency_key: "slack:message:{team_id}:{channel_id}:{message_ts}"
egress:
  - event: slack.message.post
    filter:
      channel_ids: ["C123"]
resumable: true
---
Reply to the Slack message:

{{ event.payload.text }}

Core frontmatter fields:

Field Required Meaning
name yes Human-readable name.
description yes Used as the agent system prompt.
enabled no Defaults to true; disabled agents are ignored.
resumable no Reuse agent/<slug> session state across events.
model no Per-agent {name, url} override.
accepts no Event types that can trigger the agent.
returns no Event types the agent may publish after it finishes.
tools no Capability names granted to the model.
skills no Shared Markdown skills from agents/skills/.
schedules no Cron triggers that publish synthetic events.
ingress no Connector bindings that ingest external events.
egress no Connector bindings that deliver returned events.

Schedules automatically add agent.<slug>.scheduled to accepts. For example, agents/release-manager.md with a schedule accepts agent.release-manager.scheduled.

When resumable: true, every event for the agent uses session agent/<slug>. Otherwise each event uses agent/<slug>/<event_id> so unrelated events do not share timeline.

Events

Events are durable records with:

  • type
  • source
  • object payload
  • optional idempotency_key
  • optional causality and runtime metadata

Project event schemas live under agents/events/. The JSON filename stem is the event type:

agents/events/github.pr.opened.json

The file may be a JSON Schema object directly:

{
  "type": "object",
  "required": ["number", "title"],
  "properties": {
    "number": { "type": "integer" },
    "title": { "type": "string" }
  },
  "additionalProperties": false
}

or an object with a schema field:

{
  "schema": {
    "type": "object",
    "additionalProperties": false
  }
}

External events listed in accepts and all events listed in returns must have a schema from agents/events/ or from an enabled connector. Scheduled events are registered internally with an empty object payload schema.

Returned Events

When an agent declares returns, Zeta runs the normal assistant/tool loop first. After the loop finishes, it performs one final structured generation with no tools available. The schema is derived from the declared return event schemas:

{
  "type": "release.summary.ready",
  "payload": {
    "summary": "Release notes are ready."
  }
}

The validated result is published as a durable event from agent:<slug>. Connector egress handlers can then deliver those events to external systems.

Tools And Skills

The zeta run CLI registers the built-in Commas capabilities with the local runtime. Agent tools: entries can use either the bare model name or the canonical capability id when it is unambiguous:

Tool Capability id Purpose
read commas.read Read file contents.
ls commas.ls List files.
grep commas.grep Text search.
ast_grep commas.ast_grep Structural code search.
web_search commas.web_search Web search.
query_log commas.query_log Query Commas history.
bash commas.bash Run shell commands.
edit commas.edit Edit files.
write commas.write Write files.

Capability execution goes through the registry and each capability's policy. In the local worker, mutating tools use the current staged execution contract unless the host supplies a different runtime configuration.

Shared agent skills are Markdown files under agents/skills/. The filename stem is the skill name, and agents opt in with skills:.

Connectors

Connectors contribute event schemas, ingress, push ingress, egress, and filter schemas. Installed connector packages are discovered through the zeta.event_connectors entry point group, but a project must enable them in agents/connectors.yaml:

event_connectors:
  - slack

Connector-provided event schemas are merged with agents/events/. Duplicate schemas must be identical.

Ingress and egress sections bind an agent to connector-owned events:

accepts:
  - slack.message.received
returns:
  - slack.message.post
ingress:
  - event: slack.message.received
    filter:
      channel_ids: ["C123"]
    idempotency_key: "slack:message:{team_id}:{channel_id}:{message_ts}"
egress:
  - event: slack.message.post
    filter:
      channel_ids: ["C123"]

filter is validated against the connector's filter schema. Ingress bindings require idempotency_key so connectors can avoid duplicate ingests. Egress defaults to a connector/event idempotency key when one is not supplied.

The bundled Slack connector uses:

  • SLACK_BOT_TOKEN for chat.postMessage
  • SLACK_SIGNING_SECRET for push ingress request verification

Running Agents

Zeta stores project runtime state under .zeta/ by default. Override it with --state-dir when needed.

Publish an event manually:

zeta events publish github.pr.opened \
  --payload-json '{"number":17,"title":"Fix release notes"}'

Route or execute one unit of work:

zeta run --once

Run the worker continuously:

zeta run

If enabled connectors expose push ingress, the worker also listens for HTTP requests at:

http://127.0.0.1:8080/connectors/<connector-id>

Change the host, port, route prefix, or connector allowlist:

zeta run --host 0.0.0.0 --port 8090 --route-prefix /webhooks
zeta run --connectors slack

Run the scheduler once:

zeta schedule --once

Run the scheduler continuously:

zeta schedule

In continuous mode, the scheduler checks once per minute and publishes due synthetic events such as agent.release-manager.scheduled.

Observability And Debugging

The zeta CLI reads the project runtime journal and queue:

zeta status
zeta queue [--json]
zeta attempts [--json]
zeta runs [--json]
zeta run show RUN_ID [--json]
zeta events [--type-prefix PREFIX] [--session ID] [--limit N] [--json]
zeta events publish EVENT_TYPE [--payload-json JSON] [--idempotency-key KEY]
zeta schedule status [--json]

Common flows:

# Is there work waiting, claimed, failed, or unhandled?
zeta status

# Inspect queued items.
zeta queue
zeta queue --json

# List run summaries newest in storage order.
zeta runs

# Inspect one run, including trigger event, queue item, attempt result,
# returned events, tool calls, and usage.
zeta run show run_att_qi_evt_123_issue-triage_1 --json

# Read raw durable events.
zeta events --limit 100
zeta events --type-prefix runtime.
zeta events --session agent/issue-triage

# Publish a test event idempotently.
zeta events publish laptop.resumed \
  --payload-json '{"path":"heartbeat.txt"}' \
  --idempotency-key resume-1

# Check schedule backfill and next fire time.
zeta schedule status

Plain output is tab-separated for easy shell use. JSON output exposes the underlying records, including queue item ids, attempt ids, run ids, event payloads, token usage, final summaries, and errors.

Queue statuses are shown in this order when present:

pending
available
claimed
completed
failed
cancelled
retry_scheduled
unhandled

Runtime events use the following prefixes:

  • runtime.queue_item.* for routing and queue lifecycle
  • runtime.attempt.* for worker attempts
  • runtime.egress.* for connector delivery
  • zeta.* for model, prompt, tool, and turn records
  • rpc.* for event-log JSON-RPC work

Prompt And Tool Traces

Runtime events answer "what happened?" Prompt traces answer "what exactly did the model see?" They are stored in .zeta/zeta.sqlite3, scoped by session id. The trace inspector currently lives under the Commas CLI. By default, Commas trace commands read ~/.zeta; point them at a project runtime by setting ZETA_STATE_DIR to the same state directory used by zeta run.

export ZETA_STATE_DIR=.zeta

# List recent prompts and assistant messages across agent sessions.
commas trace log --all-sessions

# List failed or successful tool calls.
commas trace tools --failed --all-sessions
commas trace tools --successful --json --all-sessions

# Inspect one agent session.
commas trace --session agent/issue-triage log
commas trace --session agent/issue-triage show 4f9d01c2
commas trace --session agent/issue-triage tree 4f9d01c2 --down

# Compare two prompts component by component.
commas trace --session agent/issue-triage diff A B --stat

# Rebuild and resend a stored prompt.
commas trace --session agent/issue-triage replay PROMPT_ID --model fast --diff

Every trace id argument accepts a full id, a unique prefix, or a ref such as turn/<turn_id>. trace replay verifies the rebuilt prompt payload against the recorded hash before sending it to the selected model.

A worked walkthrough lives in docs/demos/trace-replay.md.

JSON-RPC

zeta rpc --stdio serves newline-delimited JSON-RPC 2.0. Each line is one JSON object. Requests include jsonrpc: "2.0", an id, a method, and optional object params; notifications omit id.

Supported methods:

Method Purpose
initialize Return server and protocol metadata.
session.run Start a session run.
session.cancel Cancel an active run by run_id.
events.list List durable events by cursor, session, turn, and limit.
events.publish Append a client-authored durable event.
tools.register Register client-hosted capabilities.
tools.respond Respond to a tools.call notification.

Server notifications:

Notification Purpose
events.notify Carries a persisted runtime event.
tools.call Asks the client to execute a registered capability.

Protocol 0.1 is additive while Zeta is alpha software. Clients should ignore unknown result fields and unknown notification params.

Commas Shell Frontend

Commas is the shell frontend that ships in this repository. It targets zsh and wraps Zeta session turns in punctuation shortcuts:

commas install
commas doctor
Glyph Workflow Behavior
, ask Answer from local context.
,, propose Run until reviewed shell work is staged or an answer is returned.
,,, do Run the tool loop directly.
+ run Execute one explicit command and capture bounded output.
? status Show the current shell session status.

Examples:

, "what changed in this repo?"
,, "run the relevant tests"
,,, "update docs and run checks"
+ uv run pytest
?

The regular CLI remains available without glyphs:

commas ask [QUESTION]
commas status [--json]
commas log [--touched PATH] [--workflow W] [--since T] [--failed] [--session ID] [--cost] [--json]
commas events [--limit N] [--json] [--raw]
commas session [show|path|list|clear|transcript] [--json]
commas model [list|use|show|clear]
commas trace [--session ID] [log|tools|grep|show|tree|closure|refs|prompts|diff|replay]
commas install [--install-dir DIR] [--rc FILE] [--glyphs|--no-glyphs]
commas doctor [--json]

Commas writes shell frontend state under ~/.commas/ by default. Zeta authored agents write project runtime state under .zeta/ by default.

Development

Set up the repo:

uv sync --group dev

Run the checks used by CI:

uv run pre-commit run --all-files
uv run pytest

License

Apache-2.0. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

commas-0.6.1.tar.gz (1.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

commas-0.6.1-py3-none-any.whl (272.4 kB view details)

Uploaded Python 3

File details

Details for the file commas-0.6.1.tar.gz.

File metadata

  • Download URL: commas-0.6.1.tar.gz
  • Upload date:
  • Size: 1.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for commas-0.6.1.tar.gz
Algorithm Hash digest
SHA256 09e33ed50d17a441c9603ec0fe55346a30939f8251fee1c059e37b65f6dffa7e
MD5 ab03cbf5b69905a6328dd93c58892c12
BLAKE2b-256 eec6dcff1e7db08fa69435d6331e010c7067b2d65366185f7792998b549725f1

See more details on using hashes here.

Provenance

The following attestation bundles were made for commas-0.6.1.tar.gz:

Publisher: release.yml on rlouf/sigil

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file commas-0.6.1-py3-none-any.whl.

File metadata

  • Download URL: commas-0.6.1-py3-none-any.whl
  • Upload date:
  • Size: 272.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for commas-0.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8f0b94263b6f5455f58611e04864caa9db207936c44f52001f0055aae2ce78c8
MD5 41f1142541304f036e596c6b1a54ff33
BLAKE2b-256 9990956bff68fdd6e9f4d2e9dec685458d3e74f18a0aa18c797dffeeeea5fa6c

See more details on using hashes here.

Provenance

The following attestation bundles were made for commas-0.6.1-py3-none-any.whl:

Publisher: release.yml on rlouf/sigil

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page