Skip to main content

wex_addon_ai

Version: 18.0.0

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

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 carrying human-only as a tool, filtered by tools.tags from the agent config. Command name app::release/publish becomes tool name app__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); outside fix, the built-in palette is cut to Read, Glob, Grep
    • value mode: report_value
    • contract mode: report_contract_section
  • 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

  1. ai__agent__talk calls discover_agents(app_workdir, kernel) and discover_sessions(app_workdir, kernel).
  2. AgentsSuiteWorkdir.apply() and SessionsRootWorkdir.apply() verify (and create) the expected filesystem layout.
  3. A picker shows existing sessions + "start new"; the user picks an agent config and an optional session to resume.
  4. ClaudeAgent(io, app_workdir, kernel, config_file, debug) is constructed.
  5. If resuming: agent.resume_session(session_dir) reads the conversation.jsonl symlink to recover _session_id, replays the last five messages.
  6. 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, fires phase.before_turn, calls _run_with_spinner(prompt). e. _run_with_spinner spawns a worker thread running self.run(prompt) → asyncio.run(_run_async(prompt)). f. _run_async assembles get_system_prompt(), builds the three MCP servers, calls ClaudeSDKClient, streams blocks, links conversation.jsonl from ResultMessage.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>

  1. ai__agent__query resolves the selection and builds a ProcessRunner (wex-addon-process).
  2. ProcessRunner.run() hands the items to AgentProcessType.run() with no record.
  3. The type resolves the agent through discover_agents, builds one ClaudeAgent, then for each item of context.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. Otherwise claude_agent.run_item(prompt, action) — a one-shot turn whose agent MCP server exposes report_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).
  4. 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:

  1. Global — resources/ai/shared/context.j2 (shipped, applies to every agent).
  2. User — ~/.wex/ai/shared/context.j2 (machine-local, unversioned).
  3. Agent — identity from agent.yml + agents/<name>/context.j2 when present.
  4. App — name, type, path, env, service list from the app config + .wex/ai/shared/context.j2.
  5. Service — each active service's <service_dir>/ai/shared/context.j2; services extended by another declared service are skipped to avoid duplicate text.
  6. Phase — _active_phase.get_prompt_section(self).
  7. 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.

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: >=33.0.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

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 18.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wexample-wex-addon-ai 18.0.0
File Size Uploaded
wexample_wex_addon_ai-18.0.0.tar.gz 271.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for wexample-wex-addon-ai 18.0.0
File Interpreter ABI Platform
wexample_wex_addon_ai-18.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 617.9 kB

Release files / wexample_wex_addon_ai-18.0.0.tar.gz

Download URL wexample_wex_addon_ai-18.0.0.tar.gz
Size 271.2 kB
Tags Source
SHA-256 checksum
How to use checksums
34e304a9fa5079fc837e50fb1d2ebc644578315e829d8ff1f6cc9ab5e3ec512d
BLAKE2b-256 checksum
How to use checksums
46347ef981d3d6b236b598fb2fb7fd9745288c9a2ee49371a3e5ef3453e9b095
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-142-generic

Release files / wexample_wex_addon_ai-18.0.0-py3-none-any.whl

Download URL wexample_wex_addon_ai-18.0.0-py3-none-any.whl
Size 346.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
603dfa570e5a00f658d19cecdd97b71c210b67ab7d1dd22791fb5e0882788361
BLAKE2b-256 checksum
How to use checksums
a1f5cd91830d1ca40f4eb10ef0a8137e813f9685f9da30e74cc35f58661fcf9a
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-142-generic

Release history Release notifications | RSS feed

18.2.0

2 release files

18.1.0

2 release files

This release

18.0.0 This release

2 release files

16.0.0

2 release files

15.0.1

2 release files

15.0.0

2 release files

13.0.0

2 release files

12.1.1

2 release files

12.1.0

2 release files

11.3.2

2 release files

11.3.1

2 release files

11.3.0

2 release files

11.2.0

2 release files

11.1.0

2 release files

11.0.0

2 release files

10.0.0

2 release files

9.0.3

2 release files

9.0.2

2 release files

9.0.1

2 release files

9.0.0

2 release files

8.0.0

2 release files

7.0.0

2 release files

6.2.0

2 release files

6.1.1

2 release files

6.1.0

2 release files

6.0.38

2 release files

6.0.37

2 release files

6.0.36

2 release files

6.0.35

2 release files

6.0.34

2 release files

6.0.33

2 release files

6.0.32

2 release files

6.0.31

2 release files

6.0.29

2 release files

0.1.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page