What you will build

  • A shell hook that posts to Slack when a session ends.
  • An SDK event handler that streams tool progress to a channel.
  • A filter that suppresses notifications for sensitive sessions.

Prerequisites

  • Autohand Code installed and authenticated.
  • A Slack incoming webhook URL stored in SLACK_WEBHOOK.
  • A project directory with a .autohand/config.json file.

Step 1: add a session-end hook

{
  "hooks": {
    "on_session_end": [
      "curl -X POST $SLACK_WEBHOOK -H 'Content-type: application/json' -d '{\"text\": "Autohand session completed in {{duration}}ms"}'"
    ]
  }
}

Run a session and verify the message arrives in Slack.

Step 2: stream tool progress

Create a small event handler that streams tool_start, tool_end, and session_end events to Slack.

JavaScript

for await (const event of sdk.streamPrompt({ message: 'Deploy the api service' })) {
  if (event.type === 'session_end') {
    await fetch(process.env.SLACK_WEBHOOK, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ text: `Autohand completed in ${event.duration}ms.` })
    });
  }
}

TypeScript

for await (const event of sdk.streamPrompt({ message: 'Deploy the api service' })) {
  if (event.type === 'session_end') {
    await notifySlack({
      text: `Autohand completed in ${event.duration}ms.`,
      sessionId: event.sessionId
    });
  }
}

Python

async for event in sdk.stream_prompt("Deploy the api service"):
    if event["type"] == "session_end":
        await notify_slack({
            "text": f"Autohand completed in {event['duration']}ms.",
            "session_id": event["session_id"],
        })

Go

events, _ := sdk.StreamPrompt(ctx, "Deploy the api service")
for event := range events {
  if event.Type == "session_end" {
    notifySlack(ctx, fmt.Sprintf("Autohand completed in %dms.", event.Duration))
  }
}

Java

sdk.streamPrompt("Deploy the api service").forEach(event -> {
  if (event.type().equals("session_end")) {
    slack.notify("Autohand completed in " + event.duration() + "ms.");
  }
});

Swift

for try await event in sdk.streamPrompt("Deploy the api service") {
    if event.type == .sessionEnd {
        try await slack.notify("Autohand completed in \(event.duration)ms.")
    }
}

curl

curl -X POST "$SLACK_WEBHOOK" \
  -H "Content-Type: application/json" \
  -d '{"text":"Autohand session completed."}'

Step 3: suppress notifications

Use an environment variable to disable notifications for sensitive work.

{
  "hooks": {
    "on_session_end": [
      "if [ "$AUTOHAND_QUIET" = "1" ]; then exit 0; fi",
      "curl -X POST $SLACK_WEBHOOK -H 'Content-type: application/json' -d '{\"text\": "Session complete"}'"
    ]
  }
}

Next steps

Route different events to different channels, or build a CI reviewer bot in the next tutorial.