HomeBlog › Humanoids: agents with a Slack handle and an email address
Blog

Humanoids: agents with a Slack handle and an email address

Jul 19, 20265 min readBy the Rysh team

An autonomous agent defined in one markdown file, reachable on Slack, email, and your website chat — and governed by you.

Your CI has a Slack handle. Your monitoring has one. The standup reminder bot has one. Meanwhile the most capable piece of software your team touches — the AI agent — lives in a browser tab, waits for you to come to it, and forgets the conversation when you close the laptop.

That asymmetry always felt backwards to me. If an agent is supposed to do real work alongside a team, it should be reachable the way a teammate is reachable: mention it in a channel, email it, ping it from the website. Not "open the vendor's web app and paste context in."

I've been building rysh, an agentic terminal multiplexer where every pane can be a shell, an autonomous agent, or a live external channel. The thing this post is about is what rysh calls a humanoid: an autonomous agent that also has contact details.

An agent, plus a contacts section

A regular rysh agent is a markdown file — persona in the body, name in the frontmatter — that you spawn into a headless actor and address by name. A humanoid is the same file with one addition: a contacts section declaring the channels it answers on.

---
name: ops-bot
description: Ops humanoid for the platform team
contacts:
  slack:
    enabled: true
    bot_token: "${SLACK_BOT_TOKEN}"
    app_token: "${SLACK_APP_TOKEN}"
    reply_mode: mentions
    channels:
      - "#platform-ops"
  email:
    enabled: true
    address: "ops-bot@yourco.dev"
    password: "${OPS_BOT_EMAIL_PASSWORD}"
---
You are ops-bot, the platform team's operations assistant.

Answer questions about deploys, rollbacks, and environments from the
runbook facts below. If you don't know, say so and name the on-call.

- Deploys go through `deployctl ship <service>`; staging first, always.
- Rollback: `deployctl rollback <service> <release-id>`.
- Production deploy freeze: Fridays after 16:00 UTC.

Two things worth noticing. The secrets aren't in the file — ${SLACK_BOT_TOKEN} resolves from your environment at spawn time, so this file is safe to commit and diff like any other source. And there's no plumbing: no webhook server to write, no per-channel bot re-implementation. The channels are declared, not built.

Spawning a coworker

##humanoid spawn ops-bot.md
##humanoid channel start ops-bot slack
##humanoid channel start ops-bot email
##humanoid channels ops-bot
# slack  [connected]
# email  [connected]

That's the whole deployment story. ##humanoid channels shows per-channel status; ##humanoid channel stop ops-bot slack disconnects one channel without touching the others; ##humanoid list shows everything you've spawned. And because a humanoid is an agent underneath, the terminal-side controls work too:

@ops-bot what's the rollback command for the billing service?
@@ops-bot deactivate     # control commands: stop / activate / deactivate

@name talks to it. @@name governs it. Same grammar as every other agent in your workspace.

Now the part that makes it a humanoid: a teammate mentions @ops-bot in #platform-ops, and the answer comes back in-thread — generated from the skill file's runbook facts, by an agent running on your machine with your API key. Someone emails ops-bot@yourco.dev, and the same agent — same persona, same knowledge — handles the reply over IMAP/SMTP.

What's actually underneath

I think the architecture matters here, because it's what separates "a bot per channel" from "one agent with several phone numbers."

Each humanoid is a single actor in rysh's runtime. It owns one LLM execution loop and spawns one lightweight channel adapter per configured contact — Slack over Socket Mode, email over IMAP IDLE and SMTP, website chat over a small HTTP/WebSocket endpoint. Adapters do transport, nothing else. An inbound message from any channel becomes a contextual prompt to the same agent; the reply routes back to whichever channel it came from.

So the Slack answer and the email answer can't drift apart, because there's only one agent to drift. Fix a wrong fact in the markdown file, respawn, and every channel is corrected at once. The skill file is the single source of truth — reviewable in a pull request like anything else your team ships.

Conversations stay separate, too: the humanoid keeps a per-thread context (channel + thread ID, a 20-turn history with a 24-hour TTL), so the incident thread in Slack doesn't bleed into the pricing question that arrived by email.

The switch that makes this sane

"Should a bot post to our channels on its own?" is the right question, and rysh's answer is a per-channel governance switch: ai means the humanoid answers autonomously (every exchange logged); human means it writes a draft into your terminal pane and nothing goes out until a person confirms it. Today the draft-and-confirm flow is live for email and website chat.

Start a new humanoid in human mode, read its drafts for a week, and flip channels to ai as it earns them. That trust ladder deserves its own post — it's the next one in this series.

Honest scope

The deal on every one of these posts: what's live, what's not.

If your team has ever said "can we just put the AI in Slack?" — this is the version of that where you keep the logic, the keys, and the last word.


rysh is in private beta. If an AI coworker your team reaches on Slack, email, and your website — defined in a file you own, governed by you — sounds like your kind of thing, we're onboarding design partners.

Next in this series: One SKILL.md, three channels · governance ai|human: the draft-and-confirm switch

Try Rysh

Every pane is a shell and an AI agent — install takes one command.

Get started free →