Skip to main content

wex_addon_ai

Version: 14.2.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. It gives each agent persistent chat sessions, engram memory (facts stored as JSON files alongside source code and recalled across sessions), 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 against a single file:

wex ai::agent/query --agent addon:ai/spelling --file path/to/file.md

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, then commits the result with itself as git author. If nothing needed correcting it records a skip in the engram and exits.

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. Headless one-shot mode. Accepts --file (single file) or --selection (sweep). For each item: checks the engram for freshness, runs run_one_shot(), imprints the result, commits file + engram with the agent as git author.

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
    • one-shot: todo_write (optional), report_done, report_skip
    • 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
EngramsRootWorkdir .wex/ai/engrams/ yes — .gitignore: *.lock only
EngramsSuiteWorkdir .wex/ai/engrams/<slug>/ yes

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. Each entry is an EngramJsonFile at <root>/<key>.engram.json. Public API: recall(key) (unlocked, returns Engram | None), imprint(key, ...) (locked read-modify-write, stamps last_rev, last_decision, notes, cache_nonce), mark_in_progress / clear_in_progress (soft reservation for sweep parallelism).

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 query --agent <name> --file <path>

  1. ai__agent__query resolves the agent config by display or qualified name.
  2. Creates ClaudeAgent (no chat() call).
  3. Calls process_file_item(claude_agent, engrams, file_path, key, ...): a. git_blob_hash(file_path) → pre_rev. b. engrams.recall(key) + is_fresh(pre_rev, source_revs, cache_nonce) → skip when fresh. c. Reads contract section for the file (scope, source list, formatter writing rules) from .wex/ai/contracts/<key>.contract.yml. d. Calls claude_agent.run_one_shot(prompt) — same _run_user_turn path as chat, but _session_dir is not initialized (sweep sessions don't appear in the talk picker), and the system prompt ends with the autonomous-finish instruction. e. The agent MCP server exposes only report_done, report_skip, todo_write (no commit, no interactive tools). f. After the turn: post_rev = git_blob_hash(file_path), engrams.imprint(key, last_rev=post_rev, last_decision=..., notes=...). g. Unless --skip-commit: git add + git commit --author <agent> for file + engram.

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.

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.1.0
  • syrtis-python-client: >=6.0.0
  • wexample-api: >=6.8.0
  • wexample-wex-addon-app: >=31.0.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

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 14.2.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 14.2.0
File Size Uploaded
wexample_wex_addon_ai-14.2.0.tar.gz 248.9 kB Details

Built distribution (wheel)

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

Total release size: 578.7 kB

Release files / wexample_wex_addon_ai-14.2.0.tar.gz

Download URL wexample_wex_addon_ai-14.2.0.tar.gz
Size 248.9 kB
Tags Source
SHA-256 checksum
How to use checksums
1e9ed16c08e27d705bbe7dd252f14dc671c6c1f049f345d5ede4c240ac6975c7
BLAKE2b-256 checksum
How to use checksums
65cc35d8355a18c4fbb3e279b55358a84ccca63459aca823fb9f74908dab9a98
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-138-generic

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

Download URL wexample_wex_addon_ai-14.2.0-py3-none-any.whl
Size 329.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b1fcdee59517703781e26240dff59f15d228bdc03dcbfe09df169134ab3b1555
BLAKE2b-256 checksum
How to use checksums
05182bf9d978c62e6b4bf21b97980e6327df509ed115e4dc6c685332e065d918
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-138-generic

Release history Release notifications | RSS feed

18.2.0

2 release files

18.1.0

2 release files

18.0.0

2 release files

16.0.0

2 release files

15.0.1

2 release files

15.0.0

2 release files

This release

14.2.0 This release

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