Skip to content
This repository was archived by the owner on Aug 12, 2026. It is now read-only.

Latest commit

 

History

335 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ambient Agent — an agentic software engineer that lives in your WhatsApp group

Coworker

An agentic software engineer that lives in your WhatsApp group.

Coworker follows the team conversation, remembers the work, decides when to contribute, and uses explicit capabilities to move software forward like a regular teammate.

npm version CI status Node version Super alpha MIT license

Warning

Coworker is a super-alpha release. It proves the smallest useful version of the product: a continuing WhatsApp participant with durable GitHub Issue Management. Use a WhatsApp account and GitHub repository you can safely test with.

What is Coworker?

Coworker is an experimental, extensible agentic engineer for WhatsApp. Add it to a group where software work is already being discussed and it becomes part of that conversation: it reads the shared context, retains useful working memory, stays quiet when it has nothing to add, and acts when the team needs help.

Today, that help is deliberately narrow. Coworker can develop a bug report or feature request with the group, search for duplicates, create and organize a GitHub issue, participate in its discussion, and close or reopen it. Issue Management is the first complete Capability, not the final product.

The direction is a complete ambient software-delivery teammate:

Capability Status Intended contribution
WhatsApp Participation Available now Follow a Managed Chat, use its history, remain private, or Say once when useful
Issue Management Available now Develop, find, create, correct, discuss, close, and reopen authorized GitHub issues
Code Review Next Read pull requests, checks, and discussion; review changes and report actionable work
Implementation Planned Take a ready issue, change code, run checks, and open a pull request
Planning Planned Turn product intent into structured, sequenced, reviewable work
Delivery Planned Coordinate readiness and releases while preserving explicit human approval
Cross-chat memory Planned Connect relevant context across conversations without weakening chat isolation

The goal is not an autonomous black box that silently owns production. It is a visible team member that can carry work from intake to implementation and review, while keeping consequential approval boundaries explicit. In particular, merge authority remains a human decision until a narrower, auditable policy is deliberately designed.

What makes it ambient?

Most chat agents wait for a command, answer once, and forget. Coworker is designed around a different pattern.

It participates without requiring invocation

Every accepted message in a Managed Chat is processed. A mention or direct question can make a Window flush immediately, but no wake word is required. The Speaker decides whether a contribution would help.

It is one continuing presence

Each Managed Chat is mapped to one continuing Speaker instance using the WhatsApp chatId. Later messages return to the same canonical context rather than creating isolated one-shot conversations.

It is private by default

The model's ordinary prose is private working context. Nothing is posted back to WhatsApp unless the Speaker explicitly calls the chat-bound say Tool. Thinking and speaking are different operations.

It listens at conversation speed

A per-chat Coalescer turns bursts of messages into stable, lossless Windows. The Speaker reads the conversation as a sequence of meaningful moments instead of being interrupted once per message.

It acts through named Capabilities

The Speaker does not receive one universal command Tool. Each kind of work arrives as a cohesive Capability: a versioned Skill explains the judgment and policy, typed Tools provide direct abilities, and provider adapters remain private.

This is the reusable design pattern. The current product applies it to software delivery in WhatsApp, but the same Coworker + Capability + Admission pattern can support other ambient agentic systems.

How it works

flowchart LR
    WA["WhatsApp account"] --> ARCHIVE["Conversation Archive"]
    ARCHIVE --> GATE{"Managed Chat?"}
    GATE -->|No| RETAIN["Retain for future context"]
    GATE -->|Yes| INBOX["Managed Chat Inbox"]
    INBOX --> COALESCER["Lossless per-chat Coalescer"]
    COALESCER --> WINDOW["Stable Window"]
    WINDOW --> RELAY["Admission Relay"]
    RELAY --> FLUE["Flue dispatch: id = chatId"]
    FLUE --> SPEAKER["Continuing Speaker instance"]
    SPEAKER --> WA_CAP["WhatsApp Participation"]
    SPEAKER --> ISSUE_CAP["Issue Management"]
    WA_CAP -->|say| WA
    ISSUE_CAP --> GITHUB["Authorized GitHub repository"]
    WEBHOOK["Verified GitHub webhook"] --> RELAY

    APP_DB[("application.sqlite")] --- ARCHIVE
    APP_DB --- INBOX
    APP_DB --- RELAY
    FLUE_DB[("flue.sqlite")] --- FLUE
Loading

The separation is intentional:

Boundary What it owns
Speaker Conversational judgment and continuing private context
Skill Versioned process and policy: how to approach a kind of work
Tool One typed, validated application ability with an observable result
Host adapter WhatsApp, GitHub, or another provider's concrete API mechanics
application.sqlite Conversation Events, inbox state, Windows, admissions, webhook receipts, and operation ledgers
flue.sqlite Canonical Agent streams, accepted submissions, and independent run records
Managed credentials WhatsApp session material, GitHub authorization, and ChatGPT OAuth
ambient-agent executable Setup, validation, dependency composition, diagnostics, and foreground runtime lifecycle

This structure prevents prompt text from becoming application control flow. Skills can guide behavior without gaining new powers; Tools can perform effects without deciding when they are appropriate; provider code can change without rewriting the Agent.

Install and run

Requirements

  • macOS or Linux
  • Node.js 22.19 or newer
  • a ChatGPT Plus or Pro account
  • a WhatsApp account that can be linked as a companion device
  • a fine-grained GitHub token scoped to the repository Coworker may manage

Install the CLI:

npm install --global ambient-agent

Run guided setup:

ambient-agent init

Setup will:

  1. open the ChatGPT device-login flow;
  2. pair or restore the managed WhatsApp session;
  3. synchronize chats and let you choose the Managed Chat;
  4. discover or request a GitHub repository and scoped credential;
  5. verify the selected services; and
  6. show a final review before installing anything.

Then verify and start it:

ambient-agent status
ambient-agent doctor --live
ambient-agent start

Automatic pull-request review is deployment-gated: a host must bind an isolated Reviewer sandbox and explicitly list github.reviewRepositories. The packaged single-host CLI leaves that list empty and never executes untrusted PR code locally.

start runs in the foreground. Use Ctrl-C for a clean stop; let systemd or another process manager own background supervision in a deployment.

No model API key or application .env file is required. Coworker owns its managed configuration and credentials. The default data directory is ~/.ambient-agent on every platform (ADR 0015). Override it with --data-dir <absolute-path>. An installation created at the former platform-native default (~/Library/Application Support/ambient-agent on macOS, ${XDG_DATA_HOME:-~/.local/share}/ambient-agent on Linux) is adopted automatically and atomically on the first run; if both directories exist, the CLI fails closed and prints both paths.

Useful lifecycle commands:

Command Purpose
ambient-agent Start the control plane, and the runtime in the same process
ambient-agent init Create a validated managed installation
ambient-agent auth Replace only the managed ChatGPT authorization
ambient-agent config Review or change the Managed Chat, repository, token, or runtime port
ambient-agent start Start the non-interactive foreground runtime
ambient-agent status Inspect configuration, databases, credentials, runtime health, and counts
ambient-agent doctor Diagnose installation integrity and unresolved work
ambient-agent doctor --live Add bounded real GitHub and model readiness checks

Use ambient-agent doctor for installation integrity and unresolved (Uncertain) work.

Control plane

ambient-agent with no subcommand binds a control plane on 127.0.0.1:4747 (--control-port to move it) and keeps it bound for the life of the process, then brings the Flue runtime up in the same process. A runtime that cannot start is reported by the control plane rather than taking the process down with it, and an installation that does not exist yet is reported as not configured rather than as an error.

Every route lives under /api/ and requires Authorization: Bearer <token>; GET /api/status reports the installation state and how the runtime boot went. The token is generated once and stored at credentials/control-plane.json (mode 0600); it is handed over by file path and never written to a log or echoed to stdout. (The exception is a control plane started before ambient-agent init: there is no data directory to persist into, so that first-run token lives for the process only and is printed — to a terminal, never to a non-interactive stdout, which under a service manager is the journal.)

curl -sS -H "Authorization: Bearer $(jq -r .token ~/.ambient-agent/credentials/control-plane.json)" \
  http://127.0.0.1:4747/api/status

Logging

The runtime owns one logging root (ADR 0016). Command responses stay on stdout — status --json and doctor --json always emit valid JSON there — while diagnostics go to stderr and to rotating files.

  • Default output is concise and human-readable on a terminal: startup phases, connected services, the watched chat and repository, actionable warnings, and terminal failures. No raw JSON, no Effect fiber ids, no message bodies.
  • ambient-agent start --debug raises the level to debug: full diagnostics, inbound message traces, and raw upstream WhatsApp records.
  • ambient-agent start --log-format json forces one JSON record per stderr line for a service manager (--log-format pretty forces human lines). Without the flag, a TTY gets pretty lines and everything else gets JSON.
  • Files: every record is also written as structured JSON to <data-dir>/logs/ambient-agent.log, rotated at 10 MiB and capped at 5 files, so "what happened last night" survives without journal discipline.
  • Redaction: tokens, webhook secrets, OAuth codes, and QR payloads are censored at the root before any sink; message text is logged at debug level only.

Output printed before the application starts is outside its control: npm exec/npx install confirmations and deprecation notices, and Node.js process warnings, cannot be reformatted by Coworker. Suppress the npm install confirmation with npm exec --yes ambient-agent (or npx -y ambient-agent); silence Node process warnings, if you must, with NODE_OPTIONS=--no-warnings.

Extend Coworker

Capabilities are the canonical extension unit. The two shipped examples live together:

src/capabilities/
├── whatsapp-participation/
│   ├── skill-body.md
│   ├── tools.ts
│   └── whatsapp-port.ts
└── issue-management/
    ├── SKILL.md          # not mounted on any agent, so not in the prompt store
    ├── tools.ts
    ├── issue-repository.ts
    ├── operation-store.ts
    └── runtime.ts

To add Code Review, for example:

  1. Add src/capabilities/code-review/skill-body.md with the review policy and its own version.
  2. Define provider-neutral review interfaces rather than exposing Octokit objects to the Agent.
  3. Add narrowly scoped, typed Tools for direct reads and effects.
  4. Put real GitHub mechanics in a private adapter under src/host/.
  5. Configure the adapter from managed dependencies in src/app.ts.
  6. Add the skill to the shipped prompt catalog (packages/agents/src/prompts/catalog.ts) and mount it in src/agents/speaker.ts alongside its Tool factory.
  7. Add deterministic contract tests, behavioral Evaluation Scenarios, and separately gated live evidence.

Registration is explicit—there is no dynamic plugin scan. Skill bodies and instructions resolve from the prompt store (#375), which is seeded from the catalog on boot, so editing one afterwards is an edit, not a release:

import { PROMPT_IDS, storedInstructions, storedSkill } from "../prompts/catalog.ts";
import { createCodeReviewTools } from "../capabilities/code-review/tools.js";

export default defineAgent(({ id }) => ({
  skills: [storedSkill(PROMPT_IDS.whatsappParticipationSkill), storedSkill(PROMPT_IDS.codeReviewSkill)],
  tools: [...createWhatsAppParticipationTools(id), ...createIssueManagementTools(), ...createCodeReviewTools()],
  instructions: storedInstructions(PROMPT_IDS.speaker),
}));

Tool, Action, or Workflow?

  • Use a Tool for a direct typed application function: read a pull request, search issues, add a comment, or Say.
  • Use an Action when a reusable operation needs its own narrowly instructed agent harness.
  • Use a Bounded Workflow for independent, inspectable work such as implementing an issue or performing a substantial review. A Bounded Workflow finishes or fails and returns control to the Speaker; it does not become a second chat participant.

The stable base currently ships Tools only. Actions and software-delivery Bounded Workflows are extension seams, not hidden features.

Rules that keep extensions trustworthy

  • Bind chat-specific Tools to chatId when constructing them; do not accept an arbitrary chat ID from the model.
  • Keep Instructions short. Put changing process and policy in versioned Skills.
  • Keep provider clients behind Capability-owned interfaces.
  • Give every external mutation an application-owned Operation Identity before crossing the provider boundary.
  • Never turn a lost response into an automatic retry. Observe first; preserve an honest Uncertain state when causation cannot be proven.
  • Store application facts in application.sqlite; let Flue exclusively own flue.sqlite.
  • Test structural integrity deterministically. Evaluate model judgment separately. Record live provider proof as a third, explicit evidence class.

Memory today and tomorrow

Today, one Managed Chat maps to one continuing Speaker context. WhatsApp history Tools are permanently scoped to that chat, so one group cannot accidentally reach another group's working context.

The Conversation Archive already retains normalized events observed across the configured WhatsApp account, including events outside the Managed Chat. The Speaker cannot currently search that cross-chat history. Cross-chat and cross-thread memory will require an explicit Capability with its own authorization, relevance, and privacy rules rather than silently removing the existing boundary.

Develop from source

git clone https://github.com/AaronAbuUsama/whatsappd-github-agent.git
cd whatsappd-github-agent
pnpm install --frozen-lockfile

pnpm run typecheck
pnpm test
GITHUB_WEBHOOK_SECRET=ci-build-only-secret pnpm run build

The package exposes dist/cli/main.js as the ambient-agent executable. To test an exact local artifact rather than the registry release:

pnpm pack --pack-destination ./artifacts
npm install --global ./artifacts/ambient-agent-*.tgz
ambient-agent --data-dir "$HOME/.ambient-agent-dev" init

Behavioral evaluations run through the same public Flue HTTP interface used by production. The default command starts fresh fixture processes and runs the exact faux-model mechanics first, followed by the real-model judged suites:

export SPEAKER_FIXTURE_DATA_DIR=/path/to/initialized/non-production/data
export BRAINTRUST_API_KEY=replace-with-a-non-production-key
# Optional: choose an existing project by ID or name; the default name is "Flue".
export BRAINTRUST_PROJECT_NAME="Ambient Agent Evals"
pnpm evals

pnpm evals:deterministic runs only the credential-free mechanics family; pnpm evals:live runs only the real-model and LLM-judge family. Each command creates a run-scoped Braintrust experiment name unless BRAINTRUST_EXPERIMENT_NAME is set intentionally to append to an existing experiment. SPEAKER_EVAL_PORT can pin the otherwise dynamically allocated fixture port. Braintrust traces and experiment records are content-bearing, so use a reviewed non-production project and credential. Live model checks are not substitutes for deterministic tests, and deterministic green checks are not presented as proof of real provider delivery.

pnpm evals explicitly enables its own content-bearing Flue tracing when BRAINTRUST_API_KEY is present. A production app process does not trace from key presence alone: set BRAINTRUST_TRACING=1 alongside the key only after reviewing the destination project and data policy.

Releases

Add a Changeset with pnpm changeset whenever a pull request changes the published package. After changes merge to main, GitHub Actions maintains a Release packages pull request containing the version and changelog. Merging that reviewed release pull request asks npm to publish through Trusted Publishing; the repository does not store a long-lived npm token.

npm publishing additionally requires the ambient-agent package to trust this repository and .github/workflows/release.yml in npm's package settings. That external binding is not proven by the deterministic test suite. The first successful live publish is the proof that GitHub OIDC and npm registry acceptance work together. A Changesets pull request created by GITHUB_TOKEN may also require a maintainer to approve its CI run; approve it and wait for current-head Node 22 and Node 24 checks before merging.

Documentation

  • System architecture — the conceptual system (Brain, Speakers, Graph, Digest, control loop); §13 maps built-vs-designed
  • Architecture map — the code taxonomy: which package owns what
  • Domain language — the vocabulary used throughout the product and code
  • Status — where the reset stands and what's deferred

Current limits

This release does not yet provide the internal Planner/Coder/Verifier loop, planning, delivery automation, cross-chat Agent memory, media understanding, active-active ownership, horizontal failover, or cross-host recovery. The supported runtime is one foreground Node process owning one managed local installation.

Coworker uses whatsappd, which ultimately connects through the unofficial WhatsApp Web protocol. Automated use may carry account risk. Use a dedicated account and a repository with appropriately restricted permissions while the project remains alpha.

Contributing

The project grows in vertical Capability slices: one useful behavior, its direct abilities, deterministic integrity, behavioral evaluation, and honest live evidence. Open an issue before broad architectural work so the Capability boundary and human approval surface are explicit.

License

MIT © Aaron AbuUsama

About

A WhatsApp group-chat GitHub concierge — an Eve agent, bridged over whatsappd, that triages issues, reviews PRs, and summarizes code from a WhatsApp group.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages