Contributing to Magent
Thank you for your interest in contributing to magent! This guide will help you get started.
Current Focus
Magent’s Codex-style agent workflow alignment is implemented as a durable child-agent/job lifecycle. Before changing agent lifecycle behavior, read and update docs/AGENT_JOBS.org.
The lifecycle surface is spawn_agent, send_agent_message, wait_agent,
list_agents, and close_agent. Agent-shell renders compact lifecycle updates,
while full state persists under the parent session’s agent-jobs data. Codex
sandboxing, seatbelt, bubblewrap, and shell isolation parity are out of scope.
Development Setup
Prerequisites
- Emacs 29.1+
- gptel 0.9.8+
- transient 0.7.8+
- compat 30.1+
- yaml 1.0+
- acp 0.12.2+
- agent-shell 0.57.1+
- ripgrep (for grep tool)
Building
make compile # Byte-compile all files make test-unit # Run batch ERT unit tests make test # Run unit tests plus deterministic live smoke tests make coverage # Run ERT under built-in testcover make clean # Remove compiled files
The Makefile auto-detects ELPA dependency directories under
~/.emacs.d/elpa/. Override variables such as GPTEL_DIR, TRANSIENT_DIR,
COMPAT_DIR, or YAML_DIR when testing against nonstandard dependency
checkouts.
Code Style
Naming Conventions
- Internal functions and variables use
magent-module--namewith a double dash. - Public functions, commands, and variables use
magent-module-namewith a single dash. - Tool implementations follow
magent-tools--<name>for the internal function andmagent-tools--<name>-toolfor thegptel-toolvariable. - Optional integration code stays in its own module, for example Evil-specific behavior belongs in
magent-evil.el. - Do not use personal-config prefixes such as
+module/namein Magent source files.
File Headers
All files must include:
;;; filename.el --- Brief description -*- lexical-binding: t; -*-
Documentation
- All public functions need docstrings
- Use
;;;for section headers - Use
;;for inline comments - Update README.org for user-facing changes
- Update AGENTS.md for developer-facing changes
- Update
docs/AGENT_JOBS.orgfor child-agent lifecycle changes - Update the relevant plan before stopping interrupted plan-driven work
Testing
Running Tests
# Full suite make test # Unit tests only make test-unit # Coverage summary make coverage # Single test by regexp emacs -Q --batch -L lisp -L ~/.emacs.d/elpa/gptel-* \ -l ert -l test/magent-test.el \ --eval '(ert-run-tests-batch "test-name-regexp")'
Writing Tests
- Mock
gptel-requestwithcl-letf - Bind registries to fresh state
- Call
magent-session-resetto clear global state - Test both success and error paths
Live Testing
# Reload changed file emacsclient --eval '(load "/path/to/file.el" nil t)' # Clear the current runtime session emacsclient --eval '(magent-runtime-session-clear (magent-runtime-session-current))' # Test prompts # - Non-tool: "你好" # - Tool-use: "帮我看下 emacs 里面有多少 buffer" # - Multi-step: "帮我在 emacs 里面打开 magent 的 magit buffer"
When running real live tests against the configured gptel provider, enable
debug-on-error in the running Emacs first:
emacsclient --eval '(setq debug-on-error t)'
During and after the run, inspect *Messages*, *Backtrace*,
*magent-log* or *magent-live-test-log*, and *gptel-log*. Do not paste
raw *gptel-log* output into issues or commits without checking for provider
headers, request bodies, or API-key material.
Continuous Integration
GitHub Actions runs:
test.yml: Emacs 29.4 installation, dependency installation, byte-compile, unit tests, and deterministic live smoke tests in a temporary daemon.coverage.yml:make coverage, uploadingcoverage/testcover-summary.tsv.melpazoid.yml: MELPA-style package checks.
The melpazoid recipe includes prompt/ and skills/. Those are bundled
runtime data and must stay in the package recipe because magent-config.el,
magent-skills.el, and built-in skill-backed capabilities resolve those paths
at runtime.
Keep package metadata centralized in magent.el and magent-pkg.el. Do not
add Package-Requires headers to secondary modules; package-lint treats those
as ineffective outside the main file. Every Elisp file should include an SPDX
license identifier.
Pull Request Process
- Fork and branch — Create a feature branch from
dev - Make changes — Follow code style and add tests
- Test — Run
make testand verify manually - Document — Update relevant docs, including CI/package docs when build metadata changes
- Commit — Use conventional commits:
feat:,fix:,docs:,test: - Submit PR — Target the
devbranch
Areas for Contribution
High Priority
- Child-agent lifecycle polish and reliability, excluding sandbox parity
- Additional tool implementations
- Performance optimizations
- Test coverage improvements
- Documentation enhancements
Medium Priority
- New built-in agents
- Skill system extensions
- UI improvements
- Error handling refinements
Low Priority
- Code cleanup
- Refactoring
- Style improvements
Architecture Guidelines
Adding a New Tool
- Implement in
magent-tools.el - Add to
magent-enable-toolsdefault - Update agent permissions
- Add tests
- Document in README.org
Agent lifecycle tools are a special case. If the tool participates in spawning, messaging, waiting for, listing, resuming, inspecting, or closing child agents, keep the implementation aligned with docs/AGENT_JOBS.org and update the related tests.
Creating a New Module
- Follow dependency graph (see AGENTS.md)
- Use
;;; -*- lexical-binding: t; -*- - Require dependencies explicitly
- Add to
magent.elif needed - Write tests in
test/magent-test.el
For a new child-agent/job module, prefer a focused module such as magent-agent-job.el over expanding magent-tools.el until the lifecycle becomes hard to isolate.
Modifying the Agent Loop
- Active request/tool-loop behavior belongs in
magent-agent-loop.el - Keep using
magent-llm-gptel.elandgptel-requestfor provider transport - Add focused tests for normalized events, tool queueing, permission decisions, abort behavior, and session recording
- When changing continuation or final-response behavior, test post-tool empty completions and reasoning-only completions; reasoning must not become assistant text
- Update request generation and live-request checks when callbacks can arrive after interruption
- Do not reintroduce removed agent-loop modules; add provider-specific transport handling only in
magent-llm-gptel.el
Getting Help
- Questions: Open a GitHub discussion
- Bugs: Open an issue with reproduction steps
- Features: Open an issue to discuss before implementing
- Chat: Join discussions in issues/PRs
License
By contributing, you agree that your contributions will be licensed under GPL-3.0.