Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,11 @@ Coda doesn't just respond — it shows up on its own. Scheduled tasks run in the

**Repo Sync** — Coda pulls the latest changes from all configured repositories every 5 minutes, so it's always working with current code.

Schedules are registered automatically on app startup — no manual setup needed. They're idempotent, so restarting the app just updates existing schedules. To trigger a triage manually: `POST /triage-issues`.
**Proactive Agno Post** — every 30 minutes, Coda posts a short Agno update grounded in recent repo activity (merged PRs, open PRs, commits) or a concrete file spotlight from the local `agno` clone. It supports posting directly to a channel or replying inside a configured Slack thread.

For issue triage to post to Slack, set `TRIAGE_CHANNEL` in your env to the target channel ID (right-click channel in Slack → View details → copy ID).
Schedules are registered automatically on app startup — no manual setup needed. They're idempotent, so restarting the app just updates existing schedules. Manual triggers: `POST /triage-issues`, `POST /digest`, and `POST /proactive-agno-post`.

For issue triage to post to Slack, set `TRIAGE_CHANNEL` in your env to the target channel ID (right-click channel in Slack → View details → copy ID). For proactive Agno posts, set `PROACTIVE_POST_ENABLED=true`, `PROACTIVE_POST_CHANNEL=C09GL0WK0SU`, and optionally `PROACTIVE_POST_THREAD_TS=1775243740.375219` to keep updates in-thread.

You can also build your own scheduled tasks — automatic PR review when new PRs are opened, stale branch alerts, or convention drift detection. See `tasks/` for examples.

Expand Down Expand Up @@ -324,6 +326,10 @@ python -m evals.run --category security
| `REPOS_DIR` | No | Path to cloned repos (default: /repos) |
| `TRIAGE_CHANNEL` | No | Slack channel ID for daily issue triage |
| `DIGEST_CHANNEL` | No | Slack channel ID for daily activity digest |
| `PROACTIVE_POST_ENABLED` | No | Enables the 30-minute proactive Agno Slack post schedule |
| `PROACTIVE_POST_CHANNEL` | No | Slack channel ID for proactive Agno posts |
| `PROACTIVE_POST_THREAD_TS` | No | Optional Slack thread timestamp for in-thread proactive posts |
| `PROACTIVE_POST_REPO` | No | Repo name to source proactive updates from (default: `agno`) |
| `JWT_VERIFICATION_KEY` | Production | RBAC public key from [os.agno.com](https://os.agno.com?utm_source=github&utm_medium=example-repo&utm_campaign=agent-example&utm_content=coda&utm_term=agentos) |

## Security
Expand Down
17 changes: 17 additions & 0 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from coda.team import coda
from db import get_postgres_db
from tasks.daily_digest import run_daily_digest
from tasks.proactive_agno_post import run_proactive_agno_post
from tasks.review_issues import run_daily_triage
from tasks.sync_repos import sync_all_repos

Expand Down Expand Up @@ -81,6 +82,15 @@ def _register_schedules() -> None:
description="Daily activity digest — merged PRs, open PRs, new/stale issues",
if_exists="update",
)
if getenv("PROACTIVE_POST_ENABLED", "false").lower() == "true" and getenv("SLACK_TOKEN"):
mgr.create(
name="proactive-agno-post",
cron="*/30 * * * *",
endpoint="/proactive-agno-post",
timezone="UTC",
description="Proactive Agno Slack update every 30 minutes",
if_exists="update",
)


@asynccontextmanager
Expand Down Expand Up @@ -133,6 +143,13 @@ def daily_digest() -> dict[str, str]:
return {"status": "ok"}


@app.post("/proactive-agno-post")
def proactive_agno_post() -> dict[str, str]:
"""Run proactive Agno posting from recent repo activity or repo spotlight."""
run_proactive_agno_post()
return {"status": "ok"}


if __name__ == "__main__":
agent_os.serve(
app="app.main:app",
Expand Down
4 changes: 4 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ services:
- SLACK_SIGNING_SECRET=${SLACK_SIGNING_SECRET:-}
- TRIAGE_CHANNEL=${TRIAGE_CHANNEL:-}
- DIGEST_CHANNEL=${DIGEST_CHANNEL:-}
- PROACTIVE_POST_ENABLED=${PROACTIVE_POST_ENABLED:-false}
- PROACTIVE_POST_CHANNEL=${PROACTIVE_POST_CHANNEL:-C09GL0WK0SU}
- PROACTIVE_POST_THREAD_TS=${PROACTIVE_POST_THREAD_TS:-1775243740.375219}
- PROACTIVE_POST_REPO=${PROACTIVE_POST_REPO:-agno}
# Repos config
- REPOS_DIR=/repos
depends_on:
Expand Down
25 changes: 25 additions & 0 deletions docs/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ Background tasks on a cron schedule via Agno ScheduleManager.
- **Repo sync:** pulls latest changes every 5 minutes (`POST /sync`)
- **Daily issue triage:** classifies new issues and posts to Slack (`POST /triage-issues`)
- **Daily digest:** morning activity summary — merged PRs, open PRs, new/stale issues (`POST /digest`)
- **Proactive Agno post:** every 30 minutes, posts a repo-grounded Agno update to Slack or a configured thread (`POST /proactive-agno-post`)
- **Startup sync:** repos are synced on application startup

### 10. Daily Issue Triage
Expand Down Expand Up @@ -157,6 +158,30 @@ review, new issues, and stale issues. Pure GitHub API — no agent involved.
- Requires `GITHUB_ACCESS_TOKEN` and `SLACK_TOKEN`.
- Repos are read from `repos.yaml`.

### 12. Proactive Agno Post

Half-hour Slack update grounded in the `agno` repository. The task prefers
recent merged PRs, then active open PRs, then local git commits, and finally a
real file spotlight from the local repo clone so it never falls back to generic filler.

**Pipeline:** Fetch (GitHub API + local git) → Select → Dedupe → Format → Post (Slack SDK)

**Behavior:**
- Targets one configured repo (default: `agno`)
- Posts to Slack channel `C09GL0WK0SU` by default
- Supports optional thread replies via `PROACTIVE_POST_THREAD_TS`
- Stores a lightweight fingerprint in `/repos/.coda-state/` to avoid repeating the same signal in the same 30-minute bucket

**Schedule:** Every 30 minutes UTC. Register with `python -m tasks.proactive_agno_post --schedule`.

**Manual trigger:** `POST /proactive-agno-post` or `python -m tasks.proactive_agno_post`.

**Configuration:**
- Set `PROACTIVE_POST_ENABLED=true` to register and run it
- Set `PROACTIVE_POST_CHANNEL` to the Slack channel ID
- Set `PROACTIVE_POST_THREAD_TS` to reply in a thread instead of top-level posting
- Set `PROACTIVE_POST_REPO` to change the source repo (defaults to `agno`)

## Agents

### Coda (Team Leader)
Expand Down
7 changes: 7 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ SLACK_SIGNING_SECRET=

# DIGEST_CHANNEL=

# Enable proactive Agno updates every 30 minutes.
# Uses the configured Slack channel ID, and can optionally post into a thread.
# PROACTIVE_POST_ENABLED=false
# PROACTIVE_POST_CHANNEL=C09GL0WK0SU
# PROACTIVE_POST_THREAD_TS=1775243740.375219
# PROACTIVE_POST_REPO=agno

# ------------------------------------------
# Optional: Database
# ------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ dependencies = [
]

[project.optional-dependencies]
dev = ["mypy", "ruff"]
dev = ["mypy", "ruff", "pytest"]

[build-system]
requires = ["setuptools"]
Expand Down
Loading
Loading