wex_addon_ai
Version: 17.0.1
wex_addon_ai is a wex add-on that attaches a Claude-backed AI agent to the wex CLI, exposed through the ai agent talk command, and runs agents over selections of files as agent:run processes. It gives each agent persistent chat sessions, engram memory (what an agent found or did on each item, kept as records of the app and recalled on the next run), and MCP access to the full wex kernel command registry so the agent can read and act on the same workspace. It is aimed at developers who already use wex to manage their projects and want an AI collaborator that shares their project's context without manual copy-pasting.
Table of Contents
- Installation
- Quickstart
- Tests
- Architecture
- Integration in the Suite
- Dependencies
- Versioning & Compatibility Policy
- License
- About us
- Known Limitations & Roadmap
- Status & Compatibility
- Useful Links
- Migration Notes
Installation
pip install wexample-wex-addon-ai
Requires Python >=3.10.
Quickstart
Install the package:
pip install wexample-wex-addon-ai
The addon registers its commands with wex automatically once installed. From any directory, open an interactive session with the Claude-backed agent:
wex ai::agent/talk
On the first run inside an app directory with no agent defined yet, talk writes .wex/ai/agents/main/agent.yml — a generalist agent with no specialisation — and opens a chat prompt. Type a message; the agent has MCP access to the full wex command registry and can read and act on the same workspace.
To run an agent headlessly over files:
wex ai::agent/query --agent addon:ai/spelling --patterns "path/to/file.md" --action fix
The spelling agent (src/wexample_wex_addon_ai/resources/ai/agents/spelling/agent.yml) reads the file, corrects misspelled words in prose without touching anything else, and reports what it changed; the visit is remembered in an engram, so an unchanged file is not sent to the model again. Without --action fix, it only reports what is wrong.
Tests
This project uses pytest for testing and pytest-cov for code coverage analysis.
Installation
First, install the required testing dependencies:
.venv/bin/python -m pip install pytest pytest-cov
Basic Usage
Run all tests with coverage:
.venv/bin/python -m pytest --cov --cov-report=html
Common Commands
# Run tests with coverage for a specific module
.venv/bin/python -m pytest --cov=your_module
# Show which lines are not covered
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
# Generate an HTML coverage report
.venv/bin/python -m pytest --cov=your_module --cov-report=html
# Combine terminal and HTML reports
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
# Run specific test file with coverage
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
Viewing HTML Reports
After generating an HTML report, open htmlcov/index.html in your browser to view detailed line-by-line coverage information.
Coverage Threshold
To enforce a minimum coverage percentage:
.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
This will cause the test suite to fail if coverage drops below 80%.
Architecture
The addon is a wex command plugin that wraps the Claude Agent SDK into a session-aware, engram-tracked, MCP-served agent runtime. It contributes two user-facing commands and a shared agent layer that both commands drive.
Parts
Commands
src/wexample_wex_addon_ai/commands/agent/talk.py — wex ai::agent/talk. Discovers agents and existing sessions, presents a combined picker, creates a ClaudeAgent, optionally resumes a session, then enters the interactive chat() loop.
src/wexample_wex_addon_ai/commands/agent/query.py — wex ai::agent/query. Runs the agent:run process type (src/wexample_wex_addon_ai/process_type/agent_process_type.py) over a selection, with no process record: --selection, --patterns, --action check|dry_run|fix. For each item the type checks the engram, runs run_item(), and imprints what the agent reported.
src/wexample_wex_addon_ai/commands/engrams/clear.py and src/wexample_wex_addon_ai/commands/tracking cover engram invalidation and issue-tracking integration respectively.
Agent layer
src/wexample_wex_addon_ai/agent/abstract_agent.py owns all agent state and the interaction contract: session lifecycle (chat, run_one_shot, run_value_draft, run_contract_draft), system-prompt assembly, subject-stack management, event draining, and the spinner loop. It does not know about the SDK.
src/wexample_wex_addon_ai/agent/claude_agent.py is the Claude SDK backend. It implements run() as asyncio.run(_run_async(prompt)). Each turn it builds the MCP server map, calls ClaudeSDKClient, streams AssistantMessage / ResultMessage blocks, links conversation.jsonl, and updates token counters.
SyrtisAgent (src/wexample_wex_addon_ai/agent/syrtis_agent.py) is the concrete leaf, currently a bare subclass of AbstractAgent.
Agent config
src/wexample_wex_addon_ai/config/agent_config.py is a Protocol — the read-only contract every backing must satisfy (get_name, get_model, get_allowed_tool_tags, get_modes, get_engram_cache_nonce, …).
src/wexample_wex_addon_ai/file/agent_yaml_file.py is the app-level implementation, backed by .wex/ai/agents/<name>/agent.yml. ServiceAgentConfig (src/wexample_wex_addon_ai/config/service_agent_config.py) wraps the same YAML structure when the file lives in an addon's service directory; it is read-only, and its get_name() returns service:<svc>/<dir>.
MCP servers
Three in-process MCP servers are wired per turn by ClaudeAgent._run_async:
-
wex— built by src/wexample_wex_addon_ai/helper/mcp.py. Exposes every kernel command not carryinghuman-onlyas a tool, filtered bytools.tagsfrom the agent config. Command nameapp::release/publishbecomes tool nameapp__release__publish. Included in chat mode only. -
agent— built by src/wexample_wex_addon_ai/helper/agent_tools.py. Always-on tools whose palette depends on mode:- chat:
commit,ask_user_question,subject_open/step/close/leave,todo_write,todo_list - item mode (a process item):
report_item(findings, changes); outsidefix, the built-in palette is cut toRead,Glob,Grep - value mode:
report_value - contract mode:
report_contract_section
- chat:
-
phase— built from_active_phase.build_tools(self)when a phase is active. Gives the phase a dedicated in-band signalling channel without polluting the agent server.
Phases
src/wexample_wex_addon_ai/phase/abstract_phase.py defines the lifecycle: enter, exit, before_turn, after_turn, build_tools, get_prompt_section, get_slash_commands. At most one phase is active on an agent at a time (agent._active_phase). A phase adds its prompt section to the assembled system prompt and its tools to the phase MCP server.
Slash commands
src/wexample_wex_addon_ai/slash_command/abstract_slash_command.py defines the interface and the global registry. Each /cmd class declares NAME, DESCRIPTION, and execute(agent, args). The registry is a lazy singleton populated on first call. Active phases may extend it via get_slash_commands().
Workdirs
Five workdir types declare the expected on-disk layout under .wex/ai/ (created and verified via filestate):
| Workdir | Path (runtime) | Tracked in git |
|---|---|---|
AgentsSuiteWorkdir |
.wex/ai/agents/ |
yes |
AgentWorkdir |
.wex/ai/agents/<name>/ |
yes, contains agent.yml |
SessionsRootWorkdir |
.wex/ai/sessions/ |
no — .gitignore: */ |
SessionsSuiteWorkdir |
.wex/ai/sessions/<slug>/ |
no |
SessionWorkdir |
.wex/ai/sessions/<slug>/<id>/ |
no, holds meta.json + conversation.jsonl symlink |
The slug is derived from the qualified agent name: app:main → app-main, service:vite/main → service-vite-main.
An open subject is stored twice, under two different git regimes
open_subject writes the frame into .wex/ai/sessions/<slug>/<id>/meta.json, which is gitignored, and the entry into the app's .wex/journal/subject/<id>.md, which is committed. Nothing reconciles the two afterwards.
Reverting the journal while the session is still running therefore desynchronises them, and only the versioned half moves: the live stack keeps ids whose files no longer exist, and every subject written afterwards records a Parent that resolves to nothing. Observed 2026-08-25 — a git checkout over .wex/journal/ to undo an extraction dropped 18 hand-opened subjects along with it, and the 51 entries deposited by the next run all pointed at an absent parent.
meta.json holds titles and ids but no dates, so it cannot rebuild the entries. Restoring the files from git is the only repair.
Engram store
src/wexample_wex_addon_ai/engram/engram_store.py is the per-agent persistent memory: records of .wex/data/engram/, named by a uuid derived from the agent's identity and the item's key (record_identity in wex-core). recall(key) computes the path and reads it; imprint(key, ...) replaces the record atomically.
Freshness is checked by Engram.is_fresh(current_rev, current_source_revs, current_cache_nonce). Setting a new engram_cache_nonce: in agent.yml invalidates every existing engram for that agent.
Resources
src/wexample_wex_addon_ai/resources/ai/shared/context.j2 is the global-scope context template — the outermost layer of every agent's system prompt. It describes the wex workspace model and the operator communication style.
src/wexample_wex_addon_ai/resources/ai/agents ships seven agents usable in any project: spelling, english, maintainer, author, contractor, documenter, documenter-one-shot. Each is a directory with agent.yml and context.j2.
Middleware
src/wexample_wex_addon_ai/middleware/optional_app_middleware.py silently injects app_workdir=None when the working directory is not a recognized app, instead of emitting the warning the base AppMiddleware would. Both talk and query use it so they work equally inside and outside an app.
Call path: wex talk
ai__agent__talkcallsdiscover_agents(app_workdir, kernel)anddiscover_sessions(app_workdir, kernel).AgentsSuiteWorkdir.apply()andSessionsRootWorkdir.apply()verify (and create) the expected filesystem layout.- A picker shows existing sessions + "start new"; the user picks an agent config and an optional session to resume.
ClaudeAgent(io, app_workdir, kernel, config_file, debug)is constructed.- If resuming:
agent.resume_session(session_dir)reads theconversation.jsonlsymlink to recover_session_id, replays the last five messages. agent.chat()loops: a._ensure_session_dir()creates.wex/ai/sessions/<slug>/<timestamp>/on the first prompt. b._ensure_session_named()prompts the user if the session has no name yet. c.io.multiline_input()reads the turn; slash commands are handled by_handle_slash_command(). d._run_user_turn(prompt)drains pending system messages, firesphase.before_turn, calls_run_with_spinner(prompt). e._run_with_spinnerspawns a worker thread runningself.run(prompt)→asyncio.run(_run_async(prompt)). f._run_asyncassemblesget_system_prompt(), builds the three MCP servers, callsClaudeSDKClient, streams blocks, linksconversation.jsonlfromResultMessage.session_id, updates token counters and context-window usage. g. Back on the main thread:_bump_session_turn(),phase.after_turn(), token footer rendered.
Call path: wex ai::agent/query --agent <name> --selection <name>
ai__agent__queryresolves the selection and builds aProcessRunner(wex-addon-process).ProcessRunner.run()hands the items toAgentProcessType.run()with no record.- The type resolves the agent through
discover_agents, builds oneClaudeAgent, then for each item ofcontext.each(): a.engrams.recall(key)+is_fresh(rev, source_revs, cache_nonce)→ answered from the engram when fresh and the last visit answers the action. b. Otherwiseclaude_agent.run_item(prompt, action)— a one-shot turn whoseagentMCP server exposesreport_item; the prompt carries what the selection says about the item. c. No report fails the run on that item. A report is imprinted (never for a dry run). - The data — findings per item, changes per item — is returned as the response.
System-prompt cascade
AbstractAgent.get_system_prompt() assembles parts in this order, each wrapped in a named XML section:
- Global —
resources/ai/shared/context.j2(shipped, applies to every agent). - User —
~/.wex/ai/shared/context.j2(machine-local, unversioned). - Agent — identity from
agent.yml+agents/<name>/context.j2when present. - App — name, type, path, env, service list from the app config +
.wex/ai/shared/context.j2. - Service — each active service's
<service_dir>/ai/shared/context.j2; services extended by another declared service are skipped to avoid duplicate text. - Phase —
_active_phase.get_prompt_section(self). - Mode instruction — one-shot / value / contract closing paragraph appended last.
Templates receive app, agent, services, and core variables and may {% include %} partials from the app's .wex/ai/shared/ directory.
Integration in the Suite
This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
Related Packages
The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
Visit the Wexample Suite documentation for the complete package ecosystem.
Dependencies
- claude-agent-sdk: >=0.2.158
- syrtis-python-client: >=6.0.0
- wexample-api: >=6.8.0
- wexample-wex-addon-app: >=32.4.0
- wexample-wex-addon-process: >=4.1.0
Versioning & Compatibility Policy
Wexample packages follow Semantic Versioning (SemVer):
- MAJOR: Breaking changes
- MINOR: New features, backward compatible
- PATCH: Bug fixes, backward compatible
We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Free to use in both personal and commercial projects.
About us
Wexample stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.
This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.
Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.
Known Limitations & Roadmap
Current limitations and planned features are tracked in the GitHub issues.
See the project roadmap for upcoming features and improvements.
Status & Compatibility
Maturity: Production-ready
Python Support: >=3.10
OS Support: Linux, macOS, Windows
Status: Actively maintained
Useful Links
- Homepage: https://github.com/wexample/python-wex-addon-ai
- Documentation: docs.wexample.com
- Issue Tracker: https://github.com/wexample/python-wex-addon-ai/issues
- Discussions: https://github.com/wexample/python-wex-addon-ai/discussions
- PyPI: pypi.org/project/wexample-wex-addon-ai
Migration Notes
When upgrading between major versions, refer to the migration guides in the documentation.
Breaking changes are clearly documented with upgrade paths and examples.
Metadata
Release files for wexample-wex-addon-ai 17.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wexample_wex_addon_ai-17.0.1.tar.gz | 270.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| wexample_wex_addon_ai-17.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 615.5 kB
Release files / wexample_wex_addon_ai-17.0.1.tar.gz
| Download URL | wexample_wex_addon_ai-17.0.1.tar.gz |
|---|---|
| Size | 270.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
52d811573b91e50438a95a9e99a6e5fd40a51fed4228fbdfa823aa3f7bf6d1da
|
|
BLAKE2b-256 checksum How to use checksums |
e3073357c51ca42ccdd002ae2445a714b1b252987d833e44b5ebccd3cdc2ab8b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
pdm/2.25.9 CPython/3.12.3 Linux/6.8.0-139-generic
|
Release files / wexample_wex_addon_ai-17.0.1-py3-none-any.whl
| Download URL | wexample_wex_addon_ai-17.0.1-py3-none-any.whl |
|---|---|
| Size | 345.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
416249245c13937f1164a6c10acf9159c9a8e307adc5a8c7fbea5472f2e8a0ba
|
|
BLAKE2b-256 checksum How to use checksums |
c54cd013ad13b67eb08b90974ff6c30b0164a2350a16531703d27c7c51ca115f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
pdm/2.25.9 CPython/3.12.3 Linux/6.8.0-139-generic
|