Report
Agent → CEO report. Send a status report or question to the user (CEO) on behalf of an agent. Notifies the dashboard inbox and, when a Slack `ceoChannel` is configured, pushes a Slack message.From its SKILL.md
npx -y skills add runbear-io/aweek --skill reportAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 11 stars11 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.4 KB, as published. Nobody here has run it
aweek:report
Send a CEO report on behalf of an agent. Every report:
- Persists a notification under the sender agent's
.aweek/agents/<slug>/notifications.json, which surfaces immediately on the dashboard's inbox. - If the project's
.aweek/channels/slack/config.json(or env) provides BOTH abotTokenAND aceoChannel, posts a formatted Slack message to that channel/DM viachat.postMessage.
The skill is the canonical surface agents call autonomously during a heartbeat session (aweek exec report send …) AND the user-facing slash command for manually composing or testing a report. Use aweek:notify directly only when you need the generic notification surface without the report/question framing.
When the agent uses this autonomously
During a heartbeat session an agent decides "I should tell the CEO about this" or "I'm blocked and need a decision" — it shells out to:
echo '{
"senderSlug": "<AGENT_SLUG>",
"kind": "report",
"title": "<SHORT_TITLE>",
"body": "<DETAILED_BODY>",
"severity": "info"
}' | aweek exec report send --input-json -
Replace kind with "question" when the agent needs a decision (rather than a status update). Replace severity with "warning" (action recommended) or "error" (blocked / urgent).
You do not invoke this on the agent's behalf — agents call it themselves through Bash during their heartbeat tick. The slash command below is for the USER to manually compose a report (testing, manual escalation, or surfacing context the agent can't articulate yet).
Slash-command workflow (user-facing)
You MUST follow this exact workflow when invoked. Use aweek exec report send — never write notification JSON files directly.
Step 1: Pick the sender agent
List available agents so the user can choose which one the report should be attributed to:
echo '{"dataDir":".aweek/agents"}' \
| aweek exec agent-helpers listAllAgents --input-json -
Project each entry to { id, name, role } for display. Treat zero entries as the "create an agent first" case — direct the user to aweek hire and stop.
Step 2: Confirm sender
Ask the user via AskUserQuestion: "Which agent is sending the report?"
- Validate the selection against the list above.
Step 3: Pick the report kind
Ask the user via AskUserQuestion: "What kind of message is this?"
report— status update; no decision needed.question— agent is blocked / needs a decision from the CEO.
Step 4: Collect content
- Title (required, ≤ 200 chars):
AskUserQuestion: "Title for the report (≤ 200 chars):" - Body (required, ≤ 5000 chars):
AskUserQuestion: "Body (≤ 5000 chars). Be specific — this is what the CEO reads:" - Severity (optional):
AskUserQuestion: "Severity? (info/warning/error— defaultinfo)" - Source task (optional):
AskUserQuestion: "Link this report to a weekly-task ID? (press Enter to skip)"
Step 5: Confirm and send
Display a summary in the conversation (do not rely on Bash output rendering — re-emit as direct assistant text):
--- Report Summary ---
From: <AGENT_NAME> (<AGENT_ID>)
Kind: <KIND>
Severity: <SEVERITY>
Title: <TITLE>
Body: <BODY>
Task: <SOURCE_TASK_ID or "none">
Ask via AskUserQuestion: "Send this report?"
If confirmed, execute:
echo '{
"senderSlug": "<AGENT_ID>",
"kind": "<KIND>",
"title": "<TITLE>",
"body": "<BODY>",
"severity": "<SEVERITY>",
"sourceTaskId": "<SOURCE_TASK_ID_OR_OMIT>"
}' | aweek exec report send --input-json -
Omit severity and sourceTaskId from the JSON when the user skipped them. JSON-escape every interpolation.
The response is the { notification, deliveredToSlack, persisted } envelope. Re-emit the formatted summary as direct assistant output:
echo "$RESULT" | aweek exec report formatReportResult --input-json - --format text
Highlight:
notification.id— for traceability in.aweek/agents/<slug>/notifications.jsonand on the dashboard inbox.deliveredToSlack— reflects the actual delivery outcome:trueiff Slack returnedok: truefor thechat.postMessage.falsemeans one of (a) noceoChannelwas configured so the Slack push was deliberately skipped (only the dashboard inbox got the write — instruct the user to set one if they want Slack push), (b) Slack returnedok: false(the error code —channel_not_found,not_in_channel,invalid_auth, etc. — appears in STDERR), or (c) the network/fetch itself failed. The skill awaits the Slack POST before returning, so by the time you read this field the message has either landed in Slack or visibly failed there is no longer an "in-flight maybe" window.
If the user declines, say "Report cancelled. No notification persisted, no Slack message sent." and stop.
Configuring Slack delivery
The Slack push is opt-in per project. To enable it:
- Run
aweek slack-init(creates the Slack app and persistsbotToken/appTokeninto.aweek/channels/slack/config.json). - Add
ceoChannelto the same file — a Slack channel ID (C…/G…), user ID (U…), or DM ID (D…). The bot must already be a member of channels (C…/G…); DMs (D…) and user IDs (U…) work without membership.
The file ends up like:
{
"botToken": "xoxb-…",
"appToken": "xapp-…",
"signingSecret": "…",
"ceoChannel": "D01ABCXYZ"
}
Env-vars take precedence per the loader contract: SLACK_CEO_CHANNEL overrides the file's ceoChannel.
When ceoChannel is missing, the report still persists to the dashboard inbox — only the Slack push is skipped. The agent's aweek exec report send returns deliveredToSlack: false so the agent knows.
Validation Rules
senderSlugmust match an existing agent in.aweek/agents/.kindmust bereportorquestionexactly.titlenon-empty, ≤ 200 chars.bodynon-empty, ≤ 5000 chars.severity, when present, must beinfo/warning/error.- Slack push is fire-and-forget — a failed Slack call (e.g.
channel_not_found) does NOT roll back the notification; the failure is logged to stderr by the dispatcher's per-call channel-error sink.