diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000..6222bb3
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,14 @@
+## Summary
+
+<!-- What does this PR do? -->
+
+## Testing
+
+- [ ] `pytest`
+- [ ] `ruff check src tests`
+
+## Agent review
+
+PRs from `cursor/*` branches automatically post a kickoff comment that triggers **@codex** and **@claude**. Resolve the review debate in-thread before merging.
+
+If kickoff did not run, use **Actions → Agent review kickoff → Run workflow** with this PR number.
diff --git a/.github/workflows/agent-pr-review-kickoff.yml b/.github/workflows/agent-pr-review-kickoff.yml
new file mode 100644
index 0000000..415a6f5
--- /dev/null
+++ b/.github/workflows/agent-pr-review-kickoff.yml
@@ -0,0 +1,125 @@
+# When Cursor (or other agents) open a PR, automatically start the Codex ↔ Claude review debate.
+# Manual rerun: Actions → "Agent review kickoff" → Run workflow → enter PR number.
+
+name: Agent review kickoff
+
+on:
+  pull_request:
+    types: [opened, ready_for_review, reopened]
+  workflow_dispatch:
+    inputs:
+      pr_number:
+        description: PR number to kick off agent review on
+        required: true
+        type: number
+
+permissions:
+  contents: read
+  pull-requests: write
+  issues: write
+
+concurrency:
+  group: agent-review-kickoff-${{ github.event.pull_request.number || inputs.pr_number }}
+  cancel-in-progress: false
+
+jobs:
+  kickoff:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Resolve pull request number
+        id: pr
+        uses: actions/github-script@v7
+        with:
+          script: |
+            const prNumber =
+              context.payload.pull_request?.number ??
+              Number(context.payload.inputs?.pr_number);
+            if (!prNumber || Number.isNaN(prNumber)) {
+              core.setFailed("No pull request number available");
+              return;
+            }
+            core.setOutput("number", String(prNumber));
+
+      - name: Load pull request
+        id: load
+        uses: actions/github-script@v7
+        with:
+          script: |
+            const pr = await github.rest.pulls.get({
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              pull_number: Number("${{ steps.pr.outputs.number }}"),
+            });
+            core.setOutput("head_ref", pr.data.head.ref);
+            core.setOutput("is_draft", String(pr.data.draft));
+            core.setOutput("html_url", pr.data.html_url);
+
+      - name: Decide whether to kick off
+        id: gate
+        uses: actions/github-script@v7
+        with:
+          script: |
+            const headRef = "${{ steps.load.outputs.head_ref }}";
+            const isManual = context.eventName === "workflow_dispatch";
+            const isAgentBranch = headRef.startsWith("cursor/");
+            const shouldRun = isManual || isAgentBranch;
+            core.setOutput("should_run", shouldRun ? "true" : "false");
+            if (!shouldRun) {
+              core.info(`Skipping kickoff: head ref ${headRef} is not an agent branch`);
+            }
+
+      - name: Skip — not an agent PR
+        if: steps.gate.outputs.should_run != 'true'
+        run: echo "No agent-review kickoff needed for this PR."
+
+      - name: Post agent review kickoff comment
+        if: steps.gate.outputs.should_run == 'true'
+        uses: actions/github-script@v7
+        with:
+          script: |
+            const marker = "<!-- agent-review-kickoff -->";
+            const prNumber = Number("${{ steps.pr.outputs.number }}");
+            const isDraft = "${{ steps.load.outputs.is_draft }}" === "true";
+            const prUrl = "${{ steps.load.outputs.html_url }}";
+
+            const { data: comments } = await github.rest.issues.listComments({
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              issue_number: prNumber,
+              per_page: 100,
+            });
+            if (comments.some((c) => c.body?.includes(marker))) {
+              core.info("Kickoff comment already exists; skipping duplicate.");
+              return;
+            }
+
+            const draftNote = isDraft
+              ? "\n\n> **Note:** This PR is still a **draft**. Mark it ready for review when you want CodeRabbit and full CI gates to run; Codex and Claude can still respond below.\n"
+              : "";
+
+            const body = `${marker}
+## Agent review debate
+
+This pull request was opened by an automated agent (**Cursor Cloud Agent**). Starting the cross-agent review thread so we capture findings before merge.${draftNote}
+
+@codex review
+
+@claude Please review this PR and engage with Codex's findings — agree or disagree on each P0/P1, note missing risks, and keep the debate in this thread before merge.
+
+**Review focus (everybot)**
+- Slack scopes, token handling, and Socket Mode deployment
+- \`/idea\` channel gating and message handler edge cases
+- Tests and docs staying aligned with \`docs/SETUP.md\`
+
+Repo guidance: see [\`AGENTS.md\`](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/main/AGENTS.md).
+
+---
+<sub>Automated by [.github/workflows/agent-pr-review-kickoff.yml](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/main/.github/workflows/agent-pr-review-kickoff.yml) · PR: ${prUrl}</sub>
+`;
+
+            await github.rest.issues.createComment({
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              issue_number: prNumber,
+              body,
+            });
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..4084228
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,16 @@
+# Agent instructions (everybot)
+
+## Review guidelines
+
+When reviewing pull requests for this repository:
+
+- Treat missing or overly broad Slack OAuth scopes as **P1**.
+- Flag any code that logs or persists Slack tokens, message content with PII, or user IDs without a documented retention policy.
+- Verify `/idea` channel gating cannot be bypassed unintentionally (wrong channel, empty `CREATIVE_CHANNEL_ID`, race on `message` events).
+- Socket Mode and long-running processes must document how deploys restart the bot without duplicating event handling.
+- Prefer small, testable pure functions for parsing and validation; handlers should stay thin.
+- Documentation changes in `docs/SETUP.md` must match actual env vars and slash command names in code.
+
+## Cross-agent debate
+
+After **Codex** posts a review, **Claude** should explicitly agree or disagree with each P0/P1 item and propose concrete alternatives. **Cursor** (author) should address or rebut findings in-thread before merge.
diff --git a/README.md b/README.md
index efd7542..4bd41b5 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,9 @@
 # everybot
-all slack bot channel
+
+Slack bot for Scalinity creative and ideas channels.
+
+## Agent PR reviews
+
+Pull requests on `cursor/*` branches automatically receive a kickoff comment that triggers **@codex review** and **@claude** for an in-thread debate before merge. See `AGENTS.md` and `.github/workflows/agent-pr-review-kickoff.yml`.
+
+To manually kick off review on an existing PR: **Actions → Agent review kickoff → Run workflow**.
