An Emacs Lisp AI coding agent with multi-agent architecture, permission-based
tool access, an Elisp-native slash-command extension API through
magent-action, and LLM integration via gptel.
homepage: https://jamie-cui.github.io/magent/
Magent now uses a durable child-agent lifecycle for collaborative agent work: spawn, message, wait, list, resume/inspect, and close. The lifecycle is implemented on top of the Magent-owned agent loop while provider integration stays with gptel-request.
See docs/UI_BACKENDS.org for the supported agent-shell frontend boundary.
magent-action and skills are complementary extension points, not two ways to
define the same thing:
magent-action | Skill | |
|---|---|---|
| Primary role | An explicit Emacs or slash-command action | Reusable model instructions |
| Definition | Trusted Elisp registered with magent-action-register | A data-only SKILL.md file |
| Activation | The user enters /name or runs M-x magent-agent-shell-run-command | The user enters /$name, selects it, or a capability activates it |
| Owns | Arguments, requirements, session policy, Steps, and multi-step control | Model context and workflow guidance |
| Project trust boundary | Action Workflows are trusted installed Elisp | Project skill Markdown never executes code |
Use magent-action when you want a stable, user-triggered entry point in
Emacs. Use a skill when you want reusable expertise that the agent can apply
while handling requests. Use both when an explicit Action
should activate reusable expertise: an agent Step can select skills with
:skills and expose its exact provider tool set with :tools.
ACP advertises every visible instruction skill as /$name in agent-shell.
Skills are never projected into the Action registry: /$name selects
instruction data for one ordinary turn, while /name invokes a registered
Action. Markdown never receives trusted Elisp execution authority.
magent-action therefore makes slash commands first-class, explicit user
actions. Your init file or another trusted Elisp package can register an Action
through the public magent-action-register API without changing the agent-shell
or ACP integration. Every Action owns one generator-backed Elisp Workflow;
managed agent, process, and callback Steps provide asynchronous suspension,
cancellation, progress, and activity recording.
Registered commands are advertised to agent-shell and can be invoked as slash
input or selected with M-x magent-agent-shell-run-command. The complete
use-package example below registers /ask-name; see
docs/COMMANDS.org for the full command API and lifecycle.
- Emacs 29.1+
- gptel 0.9.8+
- compat 30.1+
- yaml 1.0+
- acp 0.13.1+
- agent-shell 0.66.1+
- ripgrep (for the
greptool)
Add the project to your Emacs load path:
(add-to-list 'load-path "/path/to/magent/lisp")
(require 'magent)
(magent-agent-shell-ensure-config)(use-package magent
:load-path "/path/to/magent/lisp"
:config
(magent-agent-shell-ensure-config))When your use-package supports the :vc keyword, it can install and load
Magent directly from Git:
(use-package magent
:vc (:url "https://github.com/Jamie-Cui/magent" :rev "master")
:ensure t
:after (agent-shell gptel)
:demand t
:custom
;; Uncomment to bypass Magent's tool permission checks and approval prompts.
;; (magent-bypass-permission t)
(magent-default-effort 'xhigh)
:config
;; Optional: append an additional personal skill directory. Later entries
;; have higher precedence and become the skill manager's install target.
(add-to-list 'magent-skill-directories
(expand-file-name "skills" user-emacs-directory)
t)
(magent-agent-shell-ensure-config)
;; Register /ask-name as an Elisp-native Magent Action.
(magent-define-workflow my-magent-ask-name (invocation)
(let ((topic
(string-trim
(or (magent-action-invocation-argument invocation) ""))))
(magent-workflow-answer
"Ask selected agent"
(if (string-empty-p topic)
"What is your name?"
(format "What is your name? Also discuss: %s" topic)))))
(magent-action-register
"ask-name"
:description "Ask the selected Magent agent to introduce itself."
:session-policy 'current
:workflow #'my-magent-ask-name
:source-layer 'user
:requires 'subr-x)):requires accepts one Emacs feature or a list of features. Magent calls
require during invocation preflight; it does not install packages or require
a project workspace. Tool requirements belong to the agent Step that needs
them. Every registration requires one :workflow and an explicit
:session-policy. A user command can override an installed package or
builtin Action with the same name. Registering the same name, layer, and
canonical scope again replaces that slot’s previous definition. The core
/compact and /skills names remain reserved.
Magent delegates all LLM communication to gptel. Configure your provider, model, and API key through gptel:
;; gptel handles provider/model/key configuration
(setq gptel-model 'claude-sonnet-4-20250514)
(setq gptel-api-key "sk-ant-...") ; or use ANTHROPIC_API_KEY env varSee gptel documentation for full provider setup (Anthropic, OpenAI, Ollama, etc.).
The only supported Magent frontend is agent-shell. Magent supplies its own agent-shell configuration and in-process ACP client, so no external ACP command is required. To start using Magent:
- Visit a file in the project you want Magent to work on.
- Run
M-x magent-start. Magent opens or reuses the project-local agent-shell buffer through its in-process ACP adapter. You can also runM-x agent-shelland select Magent after registering the configuration as shown in the installation examples above. - Type a prompt at the bottom of the agent-shell buffer and press
RETto submit it. Assistant responses, reasoning, tool calls, and permission requests are streamed into the same buffer. - Enter another prompt and press
RETto continue the project-scoped session. While a request is running, pressC-c C-cto interrupt it.
From a source buffer, M-x magent-agent-shell-prompt-region sends the active
region and M-x magent-agent-shell-ask-at-point asks about the symbol at point;
both commands submit their context through agent-shell.
Customize with M-x customize-group RET magent RET. Key settings:
| Option | Default | Description |
|---|---|---|
magent-system-prompt | (built-in) | Default system prompt for agents |
magent-enable-tools | default tool set | Globally enabled tool permission groups |
magent-project-root-function | nil | Custom project root finder |
magent-max-history | 100 | Max messages in history |
magent-request-timeout | 120 | Timeout in seconds for LLM requests |
magent-max-sampling-requests | 0 | Continuation budget; reaching it fails the turn directly, and 0 disables the guard |
magent-default-agent | "build" | Default agent for new sessions |
magent-default-effort | nil | Default reasoning effort; nil/auto uses provider default |
magent-skill-directories | user-emacs-directory/magent/skills/ | Ordered user skill roots; later entries override earlier entries |
magent-load-custom-agents | t | Load custom agents from .magent/agent/*.md |
magent-enable-audit-log | t | Persist compact audit logs for permission and sensitive actions |
magent-agent-directory | ".magent/agent" | Relative path to custom agent dir |
magent-session-directory | ~/.emacs.d/magent/sessions/ | Base directory for global sessions and per-project session subdirectories |
magent-audit-directory | nil | Override directory for audit JSONL files; defaults to magent-session-directory/audit/ |
magent-grep-program | "rg" | Path to ripgrep binary |
magent-grep-max-matches | 100 | Max matches from grep searches |
magent-glob-max-results | 500 | Maximum paths returned by one glob |
magent-glob-max-files-scanned | 50000 | Maximum filesystem entries inspected by one glob |
magent-glob-batch-size | 500 | Filesystem entries processed per event-loop slice |
magent-bash-program | "bash" | Bash-compatible executable; commands use pipefail without implicit errexit |
magent-bash-timeout | 300 | Host-owned timeout in seconds for synchronous bash commands |
magent-child-agent-max-depth | 1 | Max recursive child-agent depth; direct children are allowed by default |
magent-emacs-eval-timeout | 10 | Timeout in seconds for emacs_eval |
magent-enable-capabilities | t | Enable contextual capability resolution by default |
magent-project-instruction-file-names | ("AGENTS.md") | Scoped project instruction filenames discovered from root toward request resources |
magent-project-instructions-max-bytes | 65536 | Aggregate per-request byte limit for project instructions; nil disables discovery |
magent-audit-preview-length | 120 | Max width for persisted normalized audit path markers |
magent-include-reasoning | t | Display (t), hide but retain (ignore), or discard (nil) reasoning; never final-answer fallback |
Core, built-in agent, slash-command, and internal runtime prompts live as
editable Org files under prompts/. Files containing placeholders such as
{{project-root}} or {{instruction}} should keep those placeholders where
the dynamic value is needed; ordinary percent signs need no escaping. Skill
prompts remain self-contained in skills/*/SKILL.md. Every bundled Org prompt
must appear exactly once in prompts/manifest.txt.
| Command | Description |
|---|---|
magent-start | Open or reuse the project-local Magent agent-shell buffer |
magent-agent-shell-start | Start a fresh Magent agent-shell buffer |
magent-agent-shell-prompt-region | Send the selected region through agent-shell |
magent-agent-shell-ask-at-point | Ask about the symbol at point through agent-shell |
magent-agent-shell-interrupt | Interrupt the active Magent agent-shell request |
magent-agent-shell-run-command | Select and run a registered slash command |
magent-agent-shell-toggle-skill-for-next-request | Toggle a one-shot instruction skill |
magent-toggle-bypass-permission | Toggle permission bypass for tool filtering and approval prompts |
Prompt text is entered directly in the agent-shell buffer, and Magent streams assistant responses, tool activity, permission prompts, and session updates back through agent-shell.
Use agent-shell session options for per-session request settings. Reasoning
effort is exposed as agent-shell’s thought level session option; use
agent-shell-set-session-thought-level to choose auto, minimal, low,
medium, high, or xhigh for future turns in the current session. The
Automatic capabilities session option enables or disables contextual skill
activation without affecting explicitly selected instruction skills.
Agent-shell file mentions use ACP structured resource blocks. Magent persists those blocks with the turn and reconstructs their bodies as user-role context; local file resources also select applicable project instructions from the project root toward the attached file.
The same bypass state is also exposed as the customize option
magent-bypass-permission under M-x customize-group RET magent RET.
Magent runtime state is scoped by project, and the supported agent-shell workflow associates sessions with the current project:
- In a recognized project, prompts, agent selection, clear, and resume operate on that project’s current session.
- Saved project sessions live under
magent-session-directory/projects/<sha1(project-root)>/. - Outside any project, Magent falls back to the global session behavior and saves directly under
magent-session-directory. - Compact audit logs for permission decisions and sensitive tools are written as daily JSONL files under
magent-session-directory/audit/unlessmagent-audit-directoryis set.
Instruction skills can be selected as one-shot context for the next request.
In agent-shell, use M-x magent-agent-shell-toggle-skill-for-next-request to
toggle a skill and M-x magent-agent-shell-clear-skills-for-next-request to
clear selected skills. Selected skills are scoped to the active Magent session
and are consumed by the next prompt.
Elisp-native slash commands are registered through the public
magent-action-register API and can be selected with
M-x magent-agent-shell-run-command. Agent-shell advertises twelve bundled
commands: /explain, /fix, /init, /review, /summarize, /test,
/compact, /skills, /doctor, /memory-init, /memory-refresh, and
/memory-clear. The six prompt commands own package Org resources and
do not activate same-name skills. /summarize writes one canonical Org note
for the current Git project and accepts an optional path or semantic scope.
Every instruction skill in the exact session scope is advertised as /$name.
/skills lists those descriptors locally. Submit /$name to select a skill
for one normal turn; submit /name or use
M-x magent-agent-shell-run-command to invoke an Action. See
docs/COMMANDS.org for slash-command behavior and
the third-party Action API. Action definitions and skill descriptors are
resolved by canonical project scope, and agent-shell uses the exact session
scope for both menus and dispatch.
All skills are instruction-only and data-only. For executable extensions, use
a trusted Elisp command or add a first-class tool to Magent’s canonical tool
catalog; companion Elisp next to SKILL.md is never loaded.
Use M-x magent-find-skill to search skills.sh. The finder shows the ten
most-installed matches; RET previews a candidate, i installs it directly,
and g starts another search. M-x magent-install-skill also accepts a local
skill directory, owner/repo@skill, or a public GitHub URL.
Managed skills are copied into ~~/.emacs.d/magent/skills/<name>/~ by default.
Magent previews the source, size, file count, and any scripts or code before a
single y/n confirmation. It installs instruction skills only, does not
execute copied scripts, and records provenance in .magent-install.json.
M-x magent-delete-skill permanently deletes a selected user-level skill after
one y/n confirmation. These commands never manage project-local
.magent/skills/ or ~~/.agents/skills/~.
magent-skill-directories is ordered: later directories take precedence when
skill names collide, and its final entry is the installation target used by the
skill manager. Append a custom directory to retain the default roots while
making the custom directory the highest-priority source and installation
target:
(add-to-list 'magent-skill-directories "/path/to/skills" t)Magent uses a multi-agent architecture where different agents have different capabilities and permissions.
| Agent | Mode | Description |
|---|---|---|
build | primary | Default agent for general coding tasks with full tool access |
plan | primary | Planning agent with restricted file edits (only .magent/plan/*.md) |
explore | subagent | Fast codebase exploration (read/grep/glob/bash only) |
general | subagent | General-purpose subagent for child-agent tasks |
compaction | primary (hidden) | Session summarization / conversation compaction |
title | primary (hidden) | Conversation title generation |
summary | primary (hidden) | Pull-request style summary generation |
- primary: User-facing agents that can be selected for sessions
- subagent: Internal agents called by primary agents for subtasks
- all: Can act as either primary or subagent
Primary agents can coordinate child agents through durable jobs. A root turn can call spawn_agent to start work under a subagent profile, use list_agents and wait_agent to monitor results, send follow-up input with send_agent_message, and close work explicitly with close_agent.
Child jobs are stored in the parent session under agent-jobs with status,
prompt, metadata, result/error, and transcript state. Agent-shell shows compact
lifecycle updates. See docs/AGENT_JOBS.org for the implementation model and
boundaries.
Each agent has permission rules controlling tool access:
;; Example permission rules in an agent definition
'((read . allow)
(write . (("*.env.example" . allow)
("*.env" . deny)
("*.key" . deny)
(* . ask)))
(bash . ask)
(* . allow))Permission actions:
allow: Tool is alloweddeny: Tool is blockedask: Prompt the user for confirmation
Create custom agents by adding markdown files to .magent/agent/.
Example: ~.magent/agent/reviewer.md~
---
description: Code review specialist
mode: primary
hidden: false
temperature: 0.3
effort: high
permissions:
read: allow
write: deny
bash: deny
grep: allow
glob: allow
---
You are a code review specialist. Analyze code for:
- Bugs and potential issues
- Code style and best practices
- Performance optimizations
- Security vulnerabilities
Provide constructive feedback with specific examples.The YAML frontmatter supports:
description: Short description of the agentmode:primary,subagent, orallhidden: Hide from agent selection UItemperature: Override default temperatureeffort: Override reasoning effort:auto,minimal,low,medium,high, orxhighmodel: Override default modeloptions: Compatibility metadata retained as a mapping; it is not sent to the providersteps: Compatibility metadata retained from older agent definitionspermissions: Mapping of permission groups toallow,deny,ask, or nested file-pattern rules
The older YAML list form using entries such as (read_file . allow) remains
read-compatible, but new and saved definitions use the mapping above.
The AI agent has access to these tools (can be customized per agent):
| Tool | Side-effect | Description |
|---|---|---|
read_file | no | Read saved file contents from disk |
read_buffer | no | Read an existing file-visiting buffer, including edits |
write_file | yes | Atomically write a file; rejects dirty buffer conflicts |
write_repo_summary | yes | Update the canonical single-file Org repository summary |
edit_file | yes | Atomically replace unique text; rejects dirty conflicts |
grep | no | Regex search via ripgrep; returns file:line:content |
glob | no | Bounded, event-loop-sliced glob traversal |
bash | yes | Execute shell commands (default timeout 300s) |
emacs_eval | yes | Evaluate Emacs Lisp expressions (default timeout 10s) |
spawn_agent | yes | Start a durable child-agent job |
send_agent_message | yes | Send follow-up input to a live child job |
wait_agent | no | Wait for child jobs and return status/results |
list_agents | no | List child-agent jobs for the current session |
close_agent | yes | Close or cancel a child-agent job |
web_search | no | Search the web via DuckDuckGo |
The canonical catalog in magent-tools.el owns each tool’s name, implementation,
and permission key. Ordinary turns request all available catalog tools; command
Steps use :tools as an exact allowlist. Every implementation returns a
structured magent-tool-result; only the provider boundary converts it to text.
Each tool follows the active agent’s allow, deny, or ask rule. The
default build profile asks for shell, Emacs evaluation, and general file
writes, while some other side-effecting operations are allowed. File-specific
deny rules still apply. Permission bypass disables these checks and should be
used only deliberately.
Tool availability is controlled by:
- Global
magent-enable-toolssetting - Per-agent permission rules
Magent-owned maintenance workflows share one Action spec between agent-shell slash input and their M-x wrappers:
/memory-initorM-x magent-action-run-memory-initinitializes Emacs profile memory./memory-refreshorM-x magent-action-run-memory-refreshrefreshes the managed profile while keeping user notes./memory-clearorM-x magent-action-run-memory-cleardeactivates and clears the managed profile while retaining user notes and a snapshot./doctororM-x magent-action-run-doctorcollects bounded local diagnostics and sends one sanitized, tool-free analysis request. Use/doctor selectorC-uon the M-x command for manual probe selection.M-x magent-action-list-sessionsopens the progressive command-session viewer;M-x magent-action-cancelcancels active work.
Doctor never gives the model emacs_eval, shell, or file tools. Its probes
are trusted read-only Elisp extensions, and only path-normalized, recursively
redacted data is persisted or sent. See docs/DOCTOR.org for the
trust boundary and probe API, and docs/COMMANDS.org for the
complete user-facing workflow command reference.
This project is licensed under the GNU General Public License v3.0. See LICENSE for details.