Digital twin agent — picks Asana tasks and implements them via Claude Code
Project description
sweat — Software Engineer August Tollerup
sweat is an autonomous software engineering agent. It runs on a schedule, picks unassigned tasks from Asana, implements them using Claude Code SDK, and opens GitHub pull requests — all without human intervention. A second agent reviews PRs, and a third audits code quality.
How It Works
cli.py start
├── ImplementerAgent (x N replicas, every hour)
│ ├── 1. Fetch unassigned tasks from Asana
│ ├── 2. Filter by work type, domain, estimated time
│ ├── 3. Ask Claude to pick the most feasible task
│ ├── 4. Assign task + post proposal comment in Asana
│ ├── 5. Clone target GitHub repo to a temp dir
│ ├── 6. Run Claude Code SDK (headless) to implement
│ ├── 7. Commit + push branch, open GitHub PR
│ └── 8. Post PR link back to Asana, clean up
│
├── ReviewerAgent (every 60s)
│ ├── 1. Poll open PRs on configured repos
│ ├── 2. Skip self-authored and already-reviewed PRs
│ └── 3. Run Claude Code SDK to review, post via GitHub API
│
└── CodeReviewerAgent (daily)
├── 1. Scan repo against quality standards doc
├── 2. Identify findings, deduplicate against existing tasks
└── 3. Create Asana tasks for new findings
Project Structure
sweat/
├── cli.py # Entrypoint — runs all agent loops concurrently
├── config.py # Env vars, agent definitions, project mappings
├── agents/
│ ├── base.py # BaseAgent ABC with run_once()
│ ├── implementer.py # Picks tasks, writes code, opens PRs
│ ├── reviewer.py # Reviews open PRs
│ ├── code_reviewer.py # Audits repo quality, creates tasks
│ └── registry.py # Agent type registry
├── clients/
│ ├── asana.py # Asana API wrapper
│ └── github.py # GitHub API wrapper (PyGithub + GitPython)
├── agent.py # Claude Code SDK wrapper
├── task_selector.py # Claude picks the most feasible task
├── task_filter.py # Rule-based task filtering and sorting
├── task_claims.py # In-memory lock to prevent duplicate claims
├── audit.py # Structured JSON audit log
├── telemetry.py # OpenTelemetry traces + metrics (OTLP export)
├── prompts/
│ ├── task_prompt.py # Implementation prompt builder
│ ├── review_prompt.py # PR review prompt builder
│ └── code_review_prompt.py # Code quality audit prompt builder
├── knowledge/ # Persistent agent knowledge base
├── tests/ # 96 unit tests (all external calls mocked)
├── Dockerfile # Standalone container image
├── docker-compose.yml # Single-service compose for deployment
└── pyproject.toml # uv project config and dependencies
Quick Start
Prerequisites
- Python 3.11+
- uv package manager
- Claude Code installed and authenticated
- An Asana personal access token
- A GitHub personal access token (or GitHub App, see below)
Install
git clone <repo-url> && cd sweat
uv sync
Configure
Copy .env.example to .env and fill in your credentials:
cp .env.example .env
ASANA_TOKEN=your_asana_personal_access_token
GITHUB_TOKEN=your_github_personal_access_token
ASANA_ASSIGNEE_GID=your_asana_user_gid
ANTHROPIC_API_KEY=your_anthropic_api_key
Then edit config.py to map your Asana projects to GitHub repos:
AGENTS = [
{
"id": "impl-myproject",
"type": "implementer",
"interval": 3600,
"asana_assignee_gid": os.environ["ASANA_ASSIGNEE_GID"],
"projects": [
{
"asana_project_id": "1234567890",
"github_repo": "org/repo",
"branch_prefix": "agent/",
}
],
},
{
"id": "reviewer-myproject",
"type": "reviewer",
"interval": 60,
"projects": [
{
"github_repo": "org/repo",
"branch_prefix": "agent/",
}
],
},
]
Run
# Start all agents (implementer + reviewer + code reviewer loops)
uv run python cli.py start
# Run reviewer agents once
uv run python cli.py review
# Run code review agents once
uv run python cli.py code-review
# View recent audit log
uv run python cli.py log --last 20
# Dry run (no side effects)
uv run python main.py --dry-run
Ctrl-C or SIGTERM shuts down cleanly.
Docker
sweat ships as a standalone Docker image. It does not bundle any observability infrastructure — bring your own Grafana Cloud, Datadog, or self-hosted OTel collector.
# Build
docker compose build
# Run (credentials in .env)
docker compose up -d
The compose file mounts a persistent volume for the audit log at /app/data/audit.jsonl.
Telemetry
sweat exports OpenTelemetry traces and metrics via OTLP gRPC. To enable, set OTEL_EXPORTER_OTLP_ENDPOINT in your .env:
OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.your-provider.com:4317
If the variable is unset, telemetry is silently disabled — no errors, no overhead.
Exported metrics:
| Metric | Type | Description |
|---|---|---|
sweat.agent.runs |
Counter | Total run_once() cycles |
sweat.agent.errors |
Counter | Failed run_once() cycles |
sweat.agent.run_duration_s |
Histogram | Duration per cycle |
sweat.tasks.implemented |
Counter | Tasks successfully implemented |
sweat.prs.opened |
Counter | PRs opened |
sweat.prs.reviewed |
Counter | PRs reviewed |
sweat.claude.calls |
Counter | Claude SDK invocations |
sweat.claude.call_duration_s |
Histogram | Claude SDK call duration |
Testing
uv run pytest -v
96 tests, all run in under a second. No real API calls — Asana, GitHub, and Claude SDK are mocked at the interface boundary.
Dependencies
| Package | Purpose |
|---|---|
claude-agent-sdk |
Task selection + headless Claude Code execution |
asana |
Asana REST API client |
PyGithub |
GitHub API (PR creation, reviews) |
GitPython |
Git operations (clone, branch, push) |
python-dotenv |
.env file loading |
opentelemetry-api |
Telemetry API |
opentelemetry-sdk |
Telemetry SDK |
opentelemetry-exporter-otlp-proto-grpc |
OTLP gRPC exporter |
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sweat_agent-0.1.1.tar.gz.
File metadata
- Download URL: sweat_agent-0.1.1.tar.gz
- Upload date:
- Size: 107.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
76e19a4e4c5b0825f006458e251cf6d537fa9437a8aff6e4523008c6ea6921a3
|
|
| MD5 |
48c92e84b0698df99b87163fd0b6e67d
|
|
| BLAKE2b-256 |
60215f982cfae4d61630882ce8959518e84980a4348deb0e3ede128adb6e4454
|
Provenance
The following attestation bundles were made for sweat_agent-0.1.1.tar.gz:
Publisher:
publish.yml on 4ug-aug/sweat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sweat_agent-0.1.1.tar.gz -
Subject digest:
76e19a4e4c5b0825f006458e251cf6d537fa9437a8aff6e4523008c6ea6921a3 - Sigstore transparency entry: 1108389237
- Sigstore integration time:
-
Permalink:
4ug-aug/sweat@71e66623dd5caff28d886f2d8b0a115ffcb3477f -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/4ug-aug
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@71e66623dd5caff28d886f2d8b0a115ffcb3477f -
Trigger Event:
release
-
Statement type:
File details
Details for the file sweat_agent-0.1.1-py3-none-any.whl.
File metadata
- Download URL: sweat_agent-0.1.1-py3-none-any.whl
- Upload date:
- Size: 31.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77166328137a26c71e9a40c040d968603d0b2d5f3e1ad130df8a1339b3b5f92a
|
|
| MD5 |
233b6123de506b2d1b117034740821c7
|
|
| BLAKE2b-256 |
99503b6996adccfe98e3c23850b427f96cffb055190f325a4c83c437a98af90b
|
Provenance
The following attestation bundles were made for sweat_agent-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on 4ug-aug/sweat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sweat_agent-0.1.1-py3-none-any.whl -
Subject digest:
77166328137a26c71e9a40c040d968603d0b2d5f3e1ad130df8a1339b3b5f92a - Sigstore transparency entry: 1108389239
- Sigstore integration time:
-
Permalink:
4ug-aug/sweat@71e66623dd5caff28d886f2d8b0a115ffcb3477f -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/4ug-aug
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@71e66623dd5caff28d886f2d8b0a115ffcb3477f -
Trigger Event:
release
-
Statement type: