valet.dev

create-slack-agents

Installation

Adds this website's skill for your agents

 

Summary

Use the Valet CLI (or 1-click Deploy URL fallback) to create, deploy, and manage AI agents that live inside Slack and handle research, follow-up, sync, and reporting for Sales, Venture, Finance, Product, Compliance, Procurement, Engineering, and Nonprofit teams.

FIG. 01
FIG. 02
FIG. 03
FIG. 04
SKILL.md
298 lines

Create Slack AI Agents on Valet

Purpose

Create, deploy, and manage AI agents on the Valet platform that live inside Slack and handle research, follow-up, sync, and reporting workloads for teams in Sales, Venture, Finance, Product, Compliance, Procurement, Engineering, and Nonprofit. Valet runs each agent in an isolated cloud VM that is wired to Slack via a per-agent Slack app (so each agent gets its own @bot-name), to external tools via MCP/command connectors, and to triggers via webhook / cron / heartbeat / Slack-message channels. Agents are defined by plain-English markdown (SOUL.md) rather than code, and the entire lifecycle — scaffold → deploy → attach connectors → install in Slack → tail logs — is driven by the valet CLI. Read-only by default; the agent never sees secret values, only the tools that depend on them.

When to Use

  • A user wants an in-Slack AI teammate that summarizes Granola calls into a deal channel after each meeting.
  • A user wants a morning briefing posted to #founders-meetings 30 minutes before each calendar invite (Venture / Investing).
  • A user wants daily cash, AP, AR, and runway from Mercury posted to #finance-daily, with @mention follow-ups (Finance Ops — read-only by design).
  • A user wants an end-of-day digest of GitHub merges, deploys, and customer-visible changes in #ship-log (Product / Engineering).
  • A user wants a Slack bot that handles a recurring SOP that currently lives in a wiki page or onboarding doc — anything described in plain English ("after a PR is opened, do X, then post Y to Slack") is in scope.
  • A user has a SOUL.md already drafted and just needs it deployed to a Slack workspace.
  • A user wants to clone a 1-click template (github.com/valet-agents/*) and customize it.
  • Not when the user wants Slack-only automation with no AI reasoning (use a Zapier / Slack workflow). Not when the user needs an agent that moves money or executes irreversible actions without human confirmation — Valet's Finance template is explicitly read-only.

Workflow

The optimal path is the valet CLI. Valet publishes its own canonical operating instructions at https://valet.dev/SKILL.md — fetch and follow that document as the authoritative reference; the steps below are a focused subset for the Slack team-agent use case. If the user does not have a terminal available, fall back to the Deploy-URL path in the subsection at the end.

1. Install and authenticate

# Confirm the CLI is installed (do NOT troubleshoot brew failures — hand back to the user)
valet version || brew install valetdotdev/tap/valet

# Log in (opens a browser for OAuth)
valet auth login
valet auth whoami    # confirms session + default org + any linked project

If brew install valetdotdev/tap/valet fails for any reason, stop the workflow and ask the user to resolve brew manually — the upstream skill explicitly forbids retrying or working around brew failures.

2. Pick a starting point

Choose one:

  • From a template (fastest — every domain on valet.dev has a published template):
    valet agents create my-sales-recap --from github.com/valet-agents/granola-summaries
    valet agents create my-vc-brief    --from github.com/valet-agents/calendar-research
    valet agents create my-finance-daily --from github.com/valet-agents/mercury-reports
    valet agents create my-ship-log    --from github.com/valet-agents/github-digests
    
  • From scratch:
    valet new my-agent          # scaffolds ./my-agent with SOUL.md, AGENTS.md, channels/, skills/
    cd my-agent
    # Edit SOUL.md — define Purpose, Workflow phases, and Guardrails (Always / Never)
    
  • From the catalog (Valet-curated agent templates):
    valet agents create my-agent --from catalog:<name>
    

3. Set org-scoped secrets

Always create secrets at the org level so they can be reused across agents. Never ask the user for secret values in chat — direct them to run the command themselves:

Please run this in your terminal and confirm when done:

valet secrets set SLACK_BOT_TOKEN=<your xoxb-… token> --org <your-org>
valet secrets set GRANOLA_API_KEY=<token from Granola → Settings → Developer> --org <your-org>

4. Add the Slack channel (two-step — this is the critical gotcha)

Slack is a two-step channel on Valet, not a one-step. Step 1 is once per org; Step 2 is once per agent.

# Step 1 — once per org (a prerequisite, NOT a reusable channel)
# Generates: org-level Slack app authorization. The CLI prompts for a config token + refresh token
# from https://api.slack.com/apps → Your App Configuration Tokens.
valet channels create slack --org <your-org>

# Step 2 — once per agent. Provisions a dedicated Slack app for THIS agent with its own @bot-name.
valet channels create slack --agent my-agent --bot-name "Sales Valet"

After Step 2 the CLI opens a browser tab for the Slack OAuth install flow, polls until install completes, and prints the bot name + workspace. The user then invites @Sales Valet to one or more channels (e.g. #deals-acme).

5. Add connectors (catalog-first)

valet connectors catalog                       # browse curated connectors (GitHub, Slack, Sentry, Linear, …)
valet connectors catalog get granola-mcp       # inspect required secret slots

# Create org-scoped from the catalog (preferred)
valet connectors create granola-mcp --org <your-org>
valet connectors create github      --org <your-org>

# Attach to the agent
valet connectors attach granola-mcp --agent my-agent
valet connectors attach github      --agent my-agent

6. Verify every secret-backed command locally — non-negotiable

valet exec is the only way to run commands locally with Valet-managed secrets injected. Test each connector before deploying:

valet exec -a my-agent GRANOLA_API_KEY -- curl -H "Authorization: Bearer {{GRANOLA_API_KEY}}" https://api.granola.ai/v1/calls
valet exec -a my-agent GITHUB_TOKEN    -- npx -y @modelcontextprotocol/server-github

Any failure here will become a runtime crash after deploy. Do not skip.

7. Deploy and run the interactive test loop

valet agents deploy
valet logs -a my-agent > /tmp/valet-test.log 2>&1 &   # background tail
# Ask the user to trigger the channel (post a message, fire the cron, send the webhook).
# Stop the tail and inspect: look for mcp_call_tool_start / mcp_call_tool_done pairs and dispatch_complete.

Browser fallback — 1-click Deploy URL (no terminal)

If the user has no terminal (e.g. non-engineer admin signing up from a phone), every template on the homepage has a Deploy URL that walks them through Slack OAuth and connector setup in the dashboard:

  1. From valet.dev, click Add to Slack under the desired template card (Sales / Venture / Finance / Product). This opens https://dashboard.valet.dev/deploy?from=github.com/valet-agents/<template>.
  2. Sign up or log in at dashboard.valet.dev.
  3. The wizard walks through Slack OAuth (Step 1 + Step 2 collapsed into one flow) and each connector's secret slots.
  4. Click Deploy. The agent comes up in the same isolated VM as a CLI-deployed agent.
  5. To customize the agent's SOUL.md afterward, either valet agents link <name> from a local clone of the template repo, or push changes via valet agents drafts push <draft-id> and valet agents drafts publish <draft-id>.

The Deploy URL path only works for templates already in github.com/valet-agents/* or the Valet catalog — custom SOUL.md content requires the CLI.

Site-Specific Gotchas

  • There is an official upstream SKILL.md at https://valet.dev/SKILL.md (also discoverable via the Link: </SKILL.md>; rel="service-doc"; type="text/markdown" response header on valet.dev). It is the authoritative source for every command, flag, and edge case. Fetch it and treat it as the contract. The skill is also discoverable via the /.well-known/agent-skills/index.json link in the same header.
  • Slack is two channels, not one. valet channels create slack --org <org> is a prerequisite authorization, not a reusable channel — it lets Valet create Slack apps in your workspace. Each agent then needs its own valet channels create slack --agent <name> (or valet channels attach slack --agent <name>) which provisions a dedicated Slack app with a unique @bot-name. Forgetting Step 1 makes Step 2 error out with a directive to run Step 1 first. Forgetting Step 2 means the agent has no Slack identity.
  • --bot-name is mandatory in practice. The upstream skill says to always pass --bot-name "<Display Name>" on every per-agent Slack create/attach. Server-side defaults from agent name are unreliable across orgs.
  • Connectors must be named after the CLI command, not the npm package. A connector named agentmail works (the wrapper injects secrets when the agent types agentmail …); a connector named agentmail-cli does not (the agent's PATH has no executable by that name). The SOUL.md workflow must reference the connector name, not npx <package>.
  • Secrets are never in the shell. Regular curl / npx / node cannot read Valet secrets — they live in the control plane and are only injected by valet exec or by deployed connectors. curl https://api.example.com?key=$API_KEY always fails locally; use valet exec -a <agent> API_KEY -- curl … {{API_KEY}}.
  • Org-scoped vs. agent-scoped defaults. Default everything (secrets, connectors, channels) to --org so it can be reused across agents. Drop to --agent only when the resource is genuinely single-use (distinct credentials for the same service, per-agent rate limits, or one-off test agents). Slack is the one documented exception: per-agent Slack channels are mandatory because each one provisions a separate Slack app identity.
  • Setting an agent-scoped secret triggers a redeploy. Setting an org-scoped secret does not. Plan rollouts accordingly.
  • All deployed files are read-only at runtime. The agent can write files (e.g. MEMORY.md), but those writes do not survive the next deploy. Anything that must persist between deploys belongs in SOUL.md or a channel file, not in agent-written memory.
  • Manifest inline channels. For cron and heartbeat, declare them in valet.yaml under channels: with type: cron (or type: heartbeat) and they auto-create on valet agents create --from. No separate valet channels create step. Mutually exclusive with catalog:.
  • valet.yaml is for catalog-published / 1-click deployable agents only. Don't generate it automatically — only when the user explicitly says "yaml", "deploy button", "dashboard setup", "1-click deploy", or "setup on web". catalog: references in the manifest must match existing catalog entries verbatim, or valet manifest validate rejects it.
  • Story block in valet.yaml has length caps. Exactly 3 steps in order: triggeractionoutcome. hero ≤ 80 chars, subheadline ≤ 200 chars, step title ≤ 60, step body ≤ 140. Sweet spots are tighter (45–75 / 110–170 / 25–50 / 80–130).
  • Homebrew failures are a hard stop. The upstream skill explicitly forbids retrying or working around brew install valetdotdev/tap/valet errors. Hand the user the exact command and wait.
  • No secret values in chat, ever. Direct the user to run valet secrets set NAME=VALUE --org <org> in their own terminal and wait for explicit confirmation before moving on.

Expected Output

A successful run produces these artifacts and side-effects. Each numbered shape corresponds to a real terminal/UI state.

1. CLI agent-create success (the common path)

{
  "outcome": "deployed",
  "agent": {
    "name": "my-sales-recap",
    "org": "acme",
    "release": "v1",
    "process_state": "ready",
    "linked_directory": "/Users/me/Developer/my-sales-recap/.valet/config.json"
  },
  "channels": [
    {
      "name": "slack",
      "type": "slack",
      "agent_scope": true,
      "bot_name": "Sales Valet",
      "workspace": "acme-workspace",
      "oauth_status": "installed"
    },
    {
      "name": "heartbeat-daily",
      "type": "heartbeat",
      "every": "24h"
    }
  ],
  "connectors": [
    { "name": "granola-mcp", "type": "mcp-server", "scope": "org", "attached": true },
    { "name": "slack-mcp",   "type": "mcp-server", "scope": "org", "attached": true }
  ],
  "secrets_referenced": ["GRANOLA_API_KEY", "SLACK_BOT_TOKEN"],
  "dashboard_url": "https://dashboard.valet.dev/orgs/acme/agents/my-sales-recap"
}

2. Deploy-URL (browser fallback) success

{
  "outcome": "deployed_via_dashboard",
  "agent": {
    "name": "granola-summaries",
    "template": "github.com/valet-agents/granola-summaries",
    "org": "acme",
    "process_state": "ready"
  },
  "slack_install": "completed",
  "bot_name": "Sales Valet",
  "user_next_step": "Invite @Sales Valet to one or more deal channels (e.g. #deals-acme)."
}

3. Slack prerequisite missing (Step 1 not run)

{
  "outcome": "error",
  "command": "valet channels create slack --agent my-agent --bot-name 'Sales Valet'",
  "error_code": "SLACK_ORG_AUTH_MISSING",
  "message": "Org-level Slack authorization not found. Run `valet channels create slack --org <your-org>` first, then re-run this command.",
  "next_step": "valet channels create slack --org acme"
}

4. Connector verification failed (caught by valet exec before deploy)

{
  "outcome": "verification_failed",
  "step": "valet exec",
  "connector": "granola-mcp",
  "command": "valet exec -a my-agent GRANOLA_API_KEY -- curl ...",
  "exit_code": 401,
  "diagnosis": "Granola API rejected the token. Confirm GRANOLA_API_KEY is a personal access token minted in Granola → Settings → Developer / API, not an OAuth token.",
  "action": "Re-run `valet secrets set GRANOLA_API_KEY=<correct-token> --org <org>` and try again. Do NOT proceed to `valet agents deploy` until verification succeeds."
}

5. Homebrew install failure (hard stop)

{
  "outcome": "blocked",
  "step": "install",
  "command": "brew install valetdotdev/tap/valet",
  "message": "Homebrew install did not succeed. Per upstream skill guidance, this is not automatable — the user must resolve brew issues manually.",
  "user_instruction": "Please run `brew install valetdotdev/tap/valet` in your terminal and resolve any errors. Come back once the CLI is installed."
}

6. Catalog list (useful before adding a connector / channel)

{
  "outcome": "catalog_listed",
  "connectors": [
    { "name": "github",      "type": "mcp-server", "slots": ["GITHUB_TOKEN"] },
    { "name": "slack-mcp",   "type": "mcp-server", "slots": ["SLACK_BOT_TOKEN", "SLACK_TEAM_ID"] },
    { "name": "granola-mcp", "type": "mcp-server", "slots": ["GRANOLA_API_KEY"] },
    { "name": "linear",      "type": "mcp-server", "slots": ["LINEAR_API_KEY"] },
    { "name": "sentry",      "type": "mcp-server", "slots": ["SENTRY_AUTH_TOKEN"] }
  ],
  "channels": [
    { "name": "slack",            "type": "slack",   "slots": ["SLACK_CONFIG_TOKEN", "SLACK_REFRESH_TOKEN"] },
    { "name": "github-webhook",   "type": "webhook", "verify": "hmac-sha256", "slots": ["GITHUB_WEBHOOK_SECRET"] },
    { "name": "stripe-webhook",   "type": "webhook", "verify": "stripe",      "slots": ["STRIPE_SIGNING_SECRET"] }
  ]
}