Team onboarding · Krahnborn delivery ops

Meet Krahnie

Krahnie is our conversation-first Slack assistant for Salesforce delivery work. Talk to it in plain English in the assistant pane, a DM, or with a mention — a fast orchestrator routes your ask to one of ~40 in-process tools that read and write Salesforce, search Slack, and render the answer back as a Block Kit card. This page is the fastest way to get oriented.

Slack Socket Mode Pydantic-AI agent loop Claude Haiku + Sonnet Salesforce REST (read + write) searches only what you can see stores nothing externally
What it is How it works What you can ask Where to use it Bigger machinery Run it locally Add a tool

What it is

A standalone agent that owns its own Slack app — not a plugin.

How it works

One message → routed → a tool runs → a card comes back.

Slack
You type in the assistant pane / DM / @mention
Assistant-pane events also carry a short-lived action_token — your personal, scoped search credential.
▼  message event
Gateway · slack_gateway.py
Socket Mode transport → builds RequestContext
Fast-ack, slash commands, modals, all button/select interactivity. Captures your action_token for this turn.
▼  agent.run_turn(text, ctx)
Orchestrator · Pydantic-AI (Haiku)
Routes your plain-English ask to one tool
Built-in tools stripped, thinking disabled — a lean ~3K-token context for cheap, fast routing.
krahnie/tools/* · in-process MCP tools
The tool does the work
Queries / writes Salesforce over REST, optionally searches Slack via RTS, and writes prose with Sonnet where needed.
▼  Block Kit
Slack
Card posted back to your thread / DM / Home
Why RTS is safe & cheap: searches are scoped to what you can already see (the action_token), RTS stores no customer data externally, and the search call itself costs zero LLM tokens — only re-feeding hits to Sonnet costs anything, and most tools either reuse an existing call or feed none.

What you can ask

Just talk naturally — Krahnie figures out the rest. Or type help in Slack for the live version of this. Try the chips below verbatim.

🗓️ Your work

  • Your week-at-a-glance digest (load bar + Refresh/Snooze) — what's my week
  • Your full assigned backlog — all my cards
  • Time you've logged — how am I looking this week
  • This week's individual work-log entries — show my logs
  • Days you forgot to log to, with a one-click Log-time button — what days am I missing time

🔎 Find cards

  • A client / project / board's cards — what's going on with <client>
  • Filtered views — overdue cards I haven't logged to
  • By creator / assignee — cards assigned to <name>
  • One card's full detail — show me CARD-001234
  • Ranked "what next" shortlist — what should I work on
  • Cards gone quiet, so nothing rots newwhat cards are stale

✍️ Do things (writes always confirm first)

  • Log time (confident match → confirm card; else picker) — log 90 min to <card>
  • Correct/move an entry (before→after diff) — that should've been Tuesday
  • Create a card — new card for <client>: <task>
  • Edit one — close the <x> card · move <card> to Test
  • Comment on a card newadd a note to <card>: …
  • Reassign / re-status many at once — reassign these to me
  • Spin a request into draft cards newdraft cards from this
  • Personal reminders — remind me in an hour to email Dan

📈 Leadership & metrics

  • Throughput + request→done time — team velocity · cycle time
  • Hours per person vs capacity — utilization
  • On-time delivery % by client — are we hitting due dates
  • Client KPI scorecard — how's <client> doing
  • Team rollups — what's outstanding this week · who logged time yesterday
  • How busy the team is right now newteam capacity
  • One client's heartbeat newclient pulse for <client>

💬 Search the conversation

  • Topical RTS — workspace-wide semantic search, grounded answer + linked sources — search slack for what we decided about <X>
  • Channel catch-up — recent activity in one channel (bot must be in it) — what's happening in #channel lately
  • Card recaps fold in Slack context — summarize the work on <card>

🚀 Handoff & version control

  • Hand a card to a coding agent (Claude Code deep link, or autonomous Codex draft-PR), brief grounded in Slack — hand off <card> to an agent
  • Move a card to Test → pick the metadata you changed → Krahnie opens a PR with AI-written QA notes.
  • Move a card to Done → Krahnie drafts functional + technical docs.

📊 Usage & admin

  • Top users by activity — leaderboard
  • Krahnie spend — show me my cost
  • Paste-ready client update — status report for <client>
  • Admins: map @person to <SF name> · set <name>'s capacity to 30

🎉 Ops & fun

  • Tell the team what went sideways so we sharpen the tools — log feedback
  • Send a teammate some appreciation — warm fuzzy for @person
  • The RTS-powered swear-jar leaderboard (fines in 🌮) — swear jar
  • A couple of easter eggs hide in here. Try tell me about yourself.

Where to use it

Krahnie meets you on Slack's native surfaces — not just one chat box.

Conversational surfaces

  • Assistant pane — opens with suggested prompts; the only surface with RTS (carries your action_token).
  • DMs & @mentions — including group DMs, where it stays mention-gated.
  • App Home tab — your personal dashboard: a "Start here" priority band + open cards, each with a ⋯ menu (Log time / Summarize / Edit) and quick-action buttons.

Commands & shortcuts

  • Slash: /my-week, /logtime, /newcard, /document, /metrics, /krahnie-feedback.
  • Message shortcuts (right-click a message): Summarize this thread and Create card from message.
  • Modals with searchable pickers for guided log-time, new-card, feedback, and handoff flows.

The bigger machinery

A few subsystems do more than answer a single question.

🔁 VC capture → PR pipeline

  • Card enters Test → "Track metadata changes" card. Dev ticks the components changed, confirms a feature branch.
  • gitops.py keeps a clean managed clone, cuts feature/CARD-####-slug from the client's base branch, retrieves only the tracked components, and opens a PR via gh.

🤖 Codex first-pass

  • An autonomous attempt at a card that opens a draft PR. Krahnie spins up a locked-down Docker container (docker/codex-runner/) and runs codex exec against the repo clone inside it (codexwork.py).
  • The container is the isolation boundary: only the repo clone + scoped ChatGPT/Salesforce-sandbox auth are mounted — never host secrets. Deliberately conservative: repo allowlist, each repo pinned to a SF sandbox, hard prod denylist, draft-only, wall-clock timeout.

🔗 Cross-org ticket sync

  • ticketsync.py — pulls client tickets → idempotently upserts Card__c, pushes crosswalked status + a client-visible note back. No middleware/Apex in the client org; has a loop guard.

🔎 Real-Time Search

  • slacksearch.py wraps assistant.search.context. Powers topical search and enriches card summaries + handoff briefs.
  • Recent work: hybrid retrieval (channel history around hits), Haiku query-expansion, and context-window prioritization so windows survive the synthesis cap.

Run it locally

Krahnie runs in production as a systemd user service. Here's setup + the day-to-day commands.

1 · Setup

cd ~/krahnie
python3 -m venv .venv
./.venv/bin/python -m pip install -r requirements.txt
# .env (gitignored) holds: SLACK_BOT_TOKEN, SLACK_APP_TOKEN, SLACK_ALLOWED_USERS,
# ANTHROPIC_API_KEY, KRAHNIE_SF_ORG, KRAHNIE_SF_INSTANCE

2 · Slack scopes — standard bot scopes plus, for RTS: search:read.public, search:read.files, search:read.users. Add in the app's OAuth & Permissions and reinstall — Slack only injects the action_token once these are installed. Semantic search needs a Business+ / Enterprise+ workspace.

3 · Run as the service (it coexists with Hermes — Hermes's Slack platform is off, so the two never contend for the connection):

systemctl --user status krahnie.service        # health
journalctl --user -u krahnie.service -f         # live logs
systemctl --user restart krahnie.service        # after a code change

Manual run (debugging) — stop the service first so two clients don't both hold the socket:

systemctl --user stop krahnie.service
~/krahnie/.venv/bin/python ~/krahnie/run.py

Checks:

PYTHONPATH=~/krahnie ./.venv/bin/python scripts/smoke_sdk.py          # SDK headless go/no-go
PYTHONPATH=~/krahnie ./.venv/bin/python scripts/test_context_flow.py  # context delivery (no Slack spam)
PYTHONPATH=~/krahnie ./.venv/bin/python scripts/test_prewarm.py       # warm-client pool
clients.yaml is re-read fresh per use, so client-registry edits (nicknames, channels, default boards, repo/ticketing config) don't need a restart. Everything else does.

Add a tool

The architecture's payoff: a new workflow is small and local — the gateway/agent core stays untouched.

Tools are exposed as mcp__krahnie__<tool_name> and are framework-portable: the same objects run under the Claude Agent SDK MCP server and the Pydantic-AI loop. See an existing module like tools/week.py or one of the recent five (cardcomment, clientpulse, capacity, stalecards, draftcards) as a template.