Agents
Run memcode as an always-on assistant that answers on the channels you use and works in the projects you register.
Memcode can be your always-on assistant. One gateway runs on your machine, answers on the channels you already use, and turns each message into real work in your projects, replying with the result. Coding is one thing it can do, not the only thing.
Three ideas are kept deliberately separate:
- Agent is who you are working with: an assistant with its own identity
(
SOUL.md), memory, and skills. For examplepersonal,coder,researcher. - Project is what you are working on: a registered working directory the agent executes in. One agent works across many projects.
- Conversation is a channel thread that remembers its current agent and project, so you do not repeat yourself every message.
There is one gateway per machine, not one per repo: it owns all your channels, and a second one refuses to start instead of breaking your bots. Every task runs in its own process, so one stuck task can never freeze the gateway or your other conversations.
Prefer talking to typing config? memcode admin does
everything below by conversation.
Want to see what people actually run? The Examples section has copy-paste recipes for the ten most common automations, from a morning briefing to CI-failure diagnosis in your chat.
Set up a channel from its own page:
- Telegram
- Discord
- Slack
- Signal
- Matrix
- Mattermost
- Microsoft Teams
- Google Chat
- SMS
- GitHub
Configure
One command handles channel setup:
memcode gateway setupBot tokens are secrets, so they go in the global .env
(~/.config/memcode/.env); non-secret settings go in
~/.config/memcode/gateway.yaml. Both live in one global config dir, per machine.
The gateway keeps its own working state there too, never inside a repo.
gateway.yaml
allow_all: false # no one is allowed until you add them per channel below
webhook:
addr: ":8787" # inbound listener for GitHub, WhatsApp, Teams, Google Chat, SMS
agents:
personal: { type: assistant }
coder: { type: coding }
projects:
memcode: { path: ~/github/memcode, enabled: true } # add via `memcode project add`
default_project: memcode
channels:
telegram:
allow_from: ["123456789"] # stable user ids (not @handles); "*" allows anyone
agent: personal # which agent this channel talks to
# tier: strong # route this channel to a stronger model
schedules:
- name: standup
cron: "0 9 * * 1-5"
task: "Summarize yesterday's commits and open PRs"
deliver_to: "telegram:123456789"Agents
An agent is a lasting assistant identity with its own home at ~/.memcode/agents/<name>,
holding its identity file SOUL.md (who it is, how it behaves — the same
filename OpenClaw and Hermes use, so a migrated agent keeps its soul), its own
memory.md, and skills. Bind a channel to one with
channels.<name>.agent, or switch inside a conversation:
/agent coderAn agent's context layers on top of your user-global memory
(~/.memcode/memory.md) and the project's own memory, so a coder working in a
repo still gets that repo's full codebase intelligence. Its skills join skill
discovery the same way.
Each agent also keeps its own conversation transcript: switching /agent
switches to that agent's session in the thread, and switching back resumes
where it left off. One agent never inherits another's conversation.
An agent can also pin the model that drives it and how hard it thinks — wherever it answers, on any channel or schedule:
agents:
personal: { type: assistant }
researcher: { type: research, model: claude-opus-5, reasoning: high }Leave model unset for automatic routing and reasoning unset to let each
turn's depth be judged automatically (off, medium, and high pin it). Or
just tell memcode admin: "make the researcher always
use Opus and think hard".
Schedules
A schedule runs a task on a timer and delivers the result to a conversation, so
your assistant reports in without being asked. Each schedule has a name, a
cron expression for when, the task in plain language,
and a deliver_to target:
schedules:
- name: standup
cron: "0 9 * * 1-5" # weekdays at 09:00
task: "Summarize yesterday's commits and open PRs"
deliver_to: "telegram:123456789"cron is minute, hour, day of month, month, day of week. Common patterns:
0 9 * * 1-5 is weekdays at 9am, 0 * * * * is every hour, 0 18 * * 5 is
Friday at 6pm. Prefer intervals? Use every: "30m" instead of cron. Need it
once, not forever? at: "2026-03-01T09:00:00Z" runs a task one time and then
removes itself — "remind me at 3pm" is a schedule too.
Manage them from the terminal (the cron alias works if that's the word your
fingers know):
memcode gateway schedule list
memcode gateway schedule add standup --cron "0 9 * * 1-5" --to telegram:123456789 "Summarize yesterday's commits and open PRs"
memcode gateway schedule add remind --at 3h --to telegram:123456789 "Remind me to review the release notes"
memcode gateway schedule run standup # fire it now, don't wait
memcode gateway schedule disable standup # pause without deleting; enable resumes
memcode gateway schedule remove standupA schedule can run as a specific agent (--agent researcher) — bringing that
agent's identity, memory, and pinned model — and evaluate its cron
expression in a named timezone (--tz America/Los_Angeles).
Changes take effect on a running gateway within seconds — no restart. Or skip
the syntax entirely: tell memcode admin "every weekday
at 9am, ..." and it writes the schedule for you. Ready-made recipes live in
Examples.
Voice
A voice note sent to the bot on Telegram, WhatsApp, Signal, or as an email attachment is transcribed and treated as the task, so you can speak a job instead of typing it. Transcription needs an OpenAI or Gemini key on the gateway machine.
Replies can optionally come back as voice notes too. Set
voice_replies: in_kind under a channel in gateway.yaml to answer voice with
voice, or always to speak every reply. It is off by default.
Projects
Register the directories the gateway may work in:
memcode project add ~/github/memcode
memcode project listA message can only run against a registered project; it can never point the agent at an arbitrary path on your machine. Switch the conversation's project with:
/project memcodeSwitching affects your next message, not one already running: a task locks in its agent and project the moment the message arrives.
A channel can also be limited to specific projects with
channels.<name>.projects: useful in a shared group channel, where one
member shouldn't be able to point the conversation at your other repos:
channels:
discord:
projects: [www] # /project on this channel accepts only these idsAuthorization and triggering
Two independent checks gate a chat message.
Who. The gateway answers no one until you say so: a message is ignored
unless its sender is in that channel's allow_from. Access is granted by the
sender's permanent user id, never their @handle, so a renamed or lookalike
handle can't gain access.
When. A direct message always gets a response. In a group the bot acts only
when it is addressed (mentioned or replied-to), so ordinary chatter doesn't
trigger it. Set respond_to_all: true to act on every message. GitHub
deliveries are verified with your webhook secret, so they skip both checks.
Pairing: adding people without hunting for ids
When someone the gateway doesn't know sends the bot a direct message, the bot replies once with a short pairing code. They send you the code, and you approve them from your terminal:
memcode gateway pair # see who's asking
memcode gateway pair approve K3QP7M # let them in
memcode gateway pair deny K3QP7M # or don'tApproval takes effect within seconds, no restart. Codes expire after an hour, a stranger only ever gets one code no matter how many messages they send, and nothing they say runs before you approve them.
Safety
A gateway job runs the agent with no terminal to answer approval prompts, so the
permission gate fails closed: destructive commands are denied automatically
rather than run. A chat message cannot turn into remote code execution on your
machine, and it cannot execute against an unregistered directory. Allow-list only
people you trust, and treat allow_from: ["*"] and respond_to_all as deliberate
choices (the gateway warns at startup if either is set).
Migrate from OpenClaw or Hermes
One command moves your whole install, memory included:
memcode claw migrate # from OpenClaw
memcode hermes migrate # from HermesSee Migrate from OpenClaw or
Hermes. Migrated memory lands in your user-global store
(~/.memcode/memory.md), shared by every agent.
Run
Start the gateway:
memcode gatewayTo keep it running across logout and reboot, install it as one machine-global background service:
memcode gateway installThis writes a launchd LaunchAgent on macOS or a systemd user unit on Linux.
memcode gateway uninstall removes it. Chat channels connect outbound, so they
need no public URL; GitHub and WhatsApp are inbound webhooks served on :8787.
Reliability
The gateway is built so you can trust it with real work:
- Messages are not lost. Every message is saved before the gateway acknowledges it to the platform. If the gateway restarts or your machine reboots, pending work picks up where it left off.
- Nothing runs twice. If a platform delivers the same message again, the duplicate is recognized and dropped. A finished task is never re-run just to recover its reply; if sending the reply fails, only the send is retried until it lands.
- Conversations stay in order. Messages in one conversation are handled one at a time, in order, and a burst of messages can't overwhelm your machine.
GitHub support is focused: a failed CI run becomes a task and the result is
posted to your chat channel; it is not a full GitHub App. WhatsApp stays
inactive until Meta verifies your business. The gateway keeps its own state in
~/.config/memcode; anything a task changes stays in the project it ran in.