codex-agent-framework 0.1.22__tar.gz → 0.1.23__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/CHANGELOG.md +19 -0
- codex_agent_framework-0.1.23/PKG-INFO +649 -0
- codex_agent_framework-0.1.23/README.md +600 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/__init__.py +2 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/agent.py +7 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/cli/main.py +15 -1
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/config.py +1 -1
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/message.py +7 -4
- codex_agent_framework-0.1.23/codex_agent/stream.py +79 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/tui/chat.py +86 -19
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/tui/lifecycle.py +63 -12
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/utils.py +1 -1
- codex_agent_framework-0.1.23/codex_agent/version.py +1 -0
- codex_agent_framework-0.1.23/codex_agent_framework.egg-info/PKG-INFO +649 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent_framework.egg-info/SOURCES.txt +1 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/pyproject.toml +1 -1
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_agent.py +160 -1
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_chat.py +90 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_cli.py +49 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_messages.py +13 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_tui.py +66 -0
- codex_agent_framework-0.1.22/PKG-INFO +0 -908
- codex_agent_framework-0.1.22/README.md +0 -859
- codex_agent_framework-0.1.22/codex_agent/version.py +0 -1
- codex_agent_framework-0.1.22/codex_agent_framework.egg-info/PKG-INFO +0 -908
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/LICENSE +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/MANIFEST.in +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/__main__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/agent_runtime.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/ai.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/browser.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_commands.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/bash/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/browser/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/content/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/content/system.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/content/vision.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/desktop/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/environment/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/files/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/files/tools.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/interface/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/memory/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/planner/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/python/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/scheduler/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/subagents/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/subagents/profiles/explorer.json +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/cli/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/cli/headless.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/cli/output.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/cli/root.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/cli/runner.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/client.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/command.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/context.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/desktop.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/event.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/get_text/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/get_text/default_gitignore +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/get_text/get_text.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/get_text/simpler_get_text.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/hooks.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/image.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/latex.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/mainloop.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/plugin.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/prompts/image_generation_system_prompt.txt +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/prompts/system_prompt.txt +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/provider.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/runtime.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/scheduler.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/scripts/install-system-dependencies.sh +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/server/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/server/app.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/server/core.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/service.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/sessions.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/status.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/stream_utils.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/tool.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/tray.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/tui/__init__.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/voice.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/worker.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent_framework.egg-info/dependency_links.txt +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent_framework.egg-info/entry_points.txt +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent_framework.egg-info/requires.txt +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent_framework.egg-info/top_level.txt +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/dependencies.txt +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/setup.cfg +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_agent_runtime.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_ai.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_browser.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_builtin_config.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_cli_headless.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_cli_root.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_client.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_events.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_get_text_browser.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_hooks.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_image_message.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_local_desktop.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_memory.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_planner.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_scheduler.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_server.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_service.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_tray.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_utils.py +0 -0
- {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_worker.py +0 -0
|
@@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
This project loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and uses semantic versioning where practical.
|
|
6
6
|
|
|
7
|
+
## [0.1.23] - 2026-05-10
|
|
8
|
+
### Added
|
|
9
|
+
- Add the SDK `Agent.stream(prompt=None)` API for iterating turn events while still exposing the final `AgentTurn` through `.turn`.
|
|
10
|
+
- Add root-level `Agent.add_plugin(plugin)` as a convenience API for registering plugin tools, providers, commands, hooks, and events.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Rework the README around a faster reader path: compact quick start, clearer Python API examples, grouped extension guidance, and updated runtime/CLI documentation.
|
|
14
|
+
- Change the default runtime directory from `~/.agent_runtime` to `~/.codex-agent` and align tests, services, examples, and ignore rules with the new location.
|
|
15
|
+
- Disable voice by default so SDK agents with OpenAI keys remain text-first unless voice is explicitly enabled.
|
|
16
|
+
- Make bare `codex-agent` attach to an already-running local server when available, otherwise start a temporary TUI-bound server.
|
|
17
|
+
- Improve TUI tool-call display with immediate start/done lines, ordered text flushing before tools, compact status icons, shortened call IDs, and cleaner terminal launch environment handling.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- Restrict prompt templating to `SystemMessage` content so developer messages, user messages, assistant messages, and tool outputs remain literal.
|
|
21
|
+
- Prevent TUI tool-call start events from being buffered until step completion, allowing long-running tool calls to show immediately.
|
|
22
|
+
|
|
23
|
+
### Tests
|
|
24
|
+
- Add regression coverage for SDK streaming, root plugin registration, runtime directory defaults, CLI local-server attachment, message templating scope, TUI tool-call ordering/rendering, and terminal environment sanitization.
|
|
25
|
+
|
|
7
26
|
## [0.1.22] - 2026-05-10
|
|
8
27
|
### Changed
|
|
9
28
|
- Harden the FastAPI/SSE bridge and Textual TUI streaming path after a stabilization audit: finite SSE read timeouts, batched live deltas, synchronous replay delta flushes, and explicit stale-subscriber replacement shutdowns.
|
|
@@ -0,0 +1,649 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codex-agent-framework
|
|
3
|
+
Version: 0.1.23
|
|
4
|
+
Summary: A lightweight event-driven Codex agent runtime.
|
|
5
|
+
Author: Baptiste
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: agent,ai,codex,openai,tools
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: audioop-lts; python_version >= "3.13"
|
|
19
|
+
Requires-Dist: beautifulsoup4
|
|
20
|
+
Requires-Dist: codex-backend-sdk
|
|
21
|
+
Requires-Dist: fastapi
|
|
22
|
+
Requires-Dist: filetype
|
|
23
|
+
Requires-Dist: modict
|
|
24
|
+
Requires-Dist: mss
|
|
25
|
+
Requires-Dist: numpy
|
|
26
|
+
Requires-Dist: odfpy
|
|
27
|
+
Requires-Dist: openai
|
|
28
|
+
Requires-Dist: openpyxl
|
|
29
|
+
Requires-Dist: pathspec
|
|
30
|
+
Requires-Dist: pillow
|
|
31
|
+
Requires-Dist: playwright
|
|
32
|
+
Requires-Dist: pydub
|
|
33
|
+
Requires-Dist: pypdf
|
|
34
|
+
Requires-Dist: pynteract
|
|
35
|
+
Requires-Dist: pywinctl
|
|
36
|
+
Requires-Dist: python-docx
|
|
37
|
+
Requires-Dist: PyYAML
|
|
38
|
+
Requires-Dist: regex
|
|
39
|
+
Requires-Dist: requests
|
|
40
|
+
Requires-Dist: rich
|
|
41
|
+
Requires-Dist: textual
|
|
42
|
+
Requires-Dist: tiktoken
|
|
43
|
+
Requires-Dist: trafilatura
|
|
44
|
+
Requires-Dist: uvicorn
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: build; extra == "dev"
|
|
47
|
+
Requires-Dist: pytest; extra == "dev"
|
|
48
|
+
Dynamic: license-file
|
|
49
|
+
|
|
50
|
+
# codex-agent
|
|
51
|
+
|
|
52
|
+
`codex-agent-framework` is a local-first Python framework for building and running tool-using AI agents.
|
|
53
|
+
|
|
54
|
+
Use it as a ready-to-run terminal assistant, or import `Agent` when you want to build your own workflow in Python.
|
|
55
|
+
|
|
56
|
+
> Early alpha: APIs are still evolving and breaking changes are expected while the architecture settles.
|
|
57
|
+
|
|
58
|
+
## Quick start
|
|
59
|
+
|
|
60
|
+
Install the package:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
python -m pip install codex-agent-framework
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
For the recommended local setup, run:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
codex-agent bootstrap -- -y
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`bootstrap` installs the desktop/browser/tray dependencies, installs the user services, and starts them. It is currently aimed mostly at Debian-like Linux systems. Use an X11 session for the best desktop automation support; Wayland is fine if you do not use the desktop plugin.
|
|
73
|
+
|
|
74
|
+
Open the assistant:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
codex-agent
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
If a local agent server is already running, the TUI connects to it. Otherwise `codex-agent` starts a temporary server for that TUI session and shuts it down when the TUI exits.
|
|
81
|
+
|
|
82
|
+
Inside the TUI, start with:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
/help
|
|
86
|
+
/sessions
|
|
87
|
+
/new_session
|
|
88
|
+
/load_session latest
|
|
89
|
+
/compact
|
|
90
|
+
/config
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Use `/compact` when a long session needs to reduce its active context. It keeps a backend summary and prunes older raw history from the active session file.
|
|
94
|
+
|
|
95
|
+
Prefer the SDK? Start with this:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from codex_agent import Agent
|
|
99
|
+
|
|
100
|
+
agent = Agent(session="new")
|
|
101
|
+
turn = agent("Summarize this repository in three practical bullet points.")
|
|
102
|
+
|
|
103
|
+
print(turn.result)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Contents
|
|
107
|
+
|
|
108
|
+
- [Python API](#python-api)
|
|
109
|
+
- [Core concepts](#core-concepts)
|
|
110
|
+
- [Extending the agent](#extending-the-agent)
|
|
111
|
+
- [Built-in capabilities](#built-in-capabilities)
|
|
112
|
+
- [Running modes](#running-modes)
|
|
113
|
+
- [Configuration and runtime files](#configuration-and-runtime-files)
|
|
114
|
+
- [Development](#development)
|
|
115
|
+
- [Recent releases](#recent-releases)
|
|
116
|
+
- [Safety notes](#safety-notes)
|
|
117
|
+
|
|
118
|
+
## Python API
|
|
119
|
+
|
|
120
|
+
### Minimal agent
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from codex_agent import Agent
|
|
124
|
+
|
|
125
|
+
agent = Agent(session="new", username="Baptiste")
|
|
126
|
+
turn = agent("Summarize this repository in three practical bullet points.")
|
|
127
|
+
|
|
128
|
+
print("completed:", turn.completed)
|
|
129
|
+
print("reason:", turn.reason)
|
|
130
|
+
print("result:", turn.result)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
`agent(...)` blocks until the turn completes and returns an `AgentTurn`. Use `turn.result` for the final result; `turn.messages` and `turn.events` contain what happened during the turn.
|
|
134
|
+
|
|
135
|
+
### Stream events from a turn
|
|
136
|
+
|
|
137
|
+
Use `agent.stream(...)` when you want live events and the final turn:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from codex_agent import Agent, ResponseContentDeltaEvent
|
|
141
|
+
|
|
142
|
+
agent = Agent(session="new")
|
|
143
|
+
stream = agent.stream("Explain what this project does.")
|
|
144
|
+
|
|
145
|
+
for event in stream:
|
|
146
|
+
if isinstance(event, ResponseContentDeltaEvent):
|
|
147
|
+
print(event.delta, end="", flush=True)
|
|
148
|
+
|
|
149
|
+
turn = stream.turn
|
|
150
|
+
print("\ncompleted:", turn.completed)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`stream.turn` waits for the final `AgentTurn`; it does not expose a partial turn object.
|
|
154
|
+
|
|
155
|
+
You can get a similar effect with the event bus and a normal blocking call:
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from codex_agent import Agent, ResponseContentDeltaEvent
|
|
159
|
+
|
|
160
|
+
agent = Agent(session="new")
|
|
161
|
+
|
|
162
|
+
@agent.on(ResponseContentDeltaEvent)
|
|
163
|
+
def print_delta(event):
|
|
164
|
+
print(event.delta, end="", flush=True)
|
|
165
|
+
|
|
166
|
+
turn = agent("Explain what this project does.")
|
|
167
|
+
print("\ncompleted:", turn.completed)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Open an interactive session from Python
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
from codex_agent import Agent
|
|
174
|
+
|
|
175
|
+
agent = Agent(session="latest")
|
|
176
|
+
agent.interact()
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Voice is disabled by default. Enable it explicitly for a voice session:
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
from codex_agent import Agent
|
|
183
|
+
|
|
184
|
+
agent = Agent(
|
|
185
|
+
session="latest",
|
|
186
|
+
openai_api_key="sk-...",
|
|
187
|
+
voice_enabled=True,
|
|
188
|
+
voice="nova",
|
|
189
|
+
)
|
|
190
|
+
agent.interact()
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Add a tool
|
|
194
|
+
|
|
195
|
+
Tools are actions the model may choose to call.
|
|
196
|
+
|
|
197
|
+
For a tool without parameters, a plain docstring becomes the tool description:
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
import subprocess
|
|
201
|
+
from codex_agent import Agent, tool
|
|
202
|
+
|
|
203
|
+
@tool
|
|
204
|
+
def list_changed_files() -> list[str]:
|
|
205
|
+
"""Return modified or untracked files in the current git repository."""
|
|
206
|
+
output = subprocess.check_output(["git", "status", "--short"], text=True)
|
|
207
|
+
return [line[3:] for line in output.splitlines() if line.strip()]
|
|
208
|
+
|
|
209
|
+
agent = Agent(session="latest")
|
|
210
|
+
agent.add_tool(list_changed_files)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
For a parameterized tool, use a YAML docstring to describe the schema exposed to the model:
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
from pathlib import Path
|
|
217
|
+
from codex_agent import Agent, tool
|
|
218
|
+
|
|
219
|
+
@tool
|
|
220
|
+
def read_project_note(path: str):
|
|
221
|
+
"""
|
|
222
|
+
description: Read a UTF-8 project note file.
|
|
223
|
+
parameters:
|
|
224
|
+
path:
|
|
225
|
+
type: string
|
|
226
|
+
description: Path to the note file, relative to the current project.
|
|
227
|
+
required:
|
|
228
|
+
- path
|
|
229
|
+
"""
|
|
230
|
+
return Path(path).read_text(encoding="utf-8")
|
|
231
|
+
|
|
232
|
+
agent = Agent(session="latest")
|
|
233
|
+
agent.add_tool(read_project_note)
|
|
234
|
+
agent("Look at my project notes and tell me what changed recently.")
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Add live context
|
|
238
|
+
|
|
239
|
+
Providers inject fresh context before a model call without saving it as permanent conversation history.
|
|
240
|
+
|
|
241
|
+
```python
|
|
242
|
+
from datetime import datetime
|
|
243
|
+
from zoneinfo import ZoneInfo
|
|
244
|
+
from codex_agent import Agent, provider
|
|
245
|
+
|
|
246
|
+
@provider
|
|
247
|
+
def current_time():
|
|
248
|
+
now = datetime.now(ZoneInfo("Europe/Paris"))
|
|
249
|
+
return f"Current local time: {now:%Y-%m-%d %H:%M:%S %Z}"
|
|
250
|
+
|
|
251
|
+
agent = Agent(session="latest")
|
|
252
|
+
agent.add_provider(current_time)
|
|
253
|
+
agent("Given the current time, should I start a long-running task now?")
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Add a slash command
|
|
257
|
+
|
|
258
|
+
Commands are explicit user actions triggered with `/name`.
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
from codex_agent import Agent, command, get_agent
|
|
262
|
+
|
|
263
|
+
@command
|
|
264
|
+
def repo():
|
|
265
|
+
"""Show the active session and current repository hint."""
|
|
266
|
+
agent = get_agent()
|
|
267
|
+
return f"session={agent.current_session_id}; repo=codex-agent"
|
|
268
|
+
|
|
269
|
+
agent = Agent(session="latest")
|
|
270
|
+
agent.add_command(repo)
|
|
271
|
+
print(agent("/repo").result)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Core concepts
|
|
275
|
+
|
|
276
|
+
The framework is built around a few extension points:
|
|
277
|
+
|
|
278
|
+
| Concept | What it is for |
|
|
279
|
+
| --- | --- |
|
|
280
|
+
| Session | Saved conversation and agent state. |
|
|
281
|
+
| Turn | One user request plus the model/tool loop needed to answer it. |
|
|
282
|
+
| Tool | An action the model may choose to call. |
|
|
283
|
+
| Provider | Fresh context injected before a response, not saved as chat history. |
|
|
284
|
+
| Command | A user-triggered operation such as `/compact` or `/config`. |
|
|
285
|
+
| Plugin | A bundle of state, tools, providers, commands, events, hooks, and prompt text. |
|
|
286
|
+
|
|
287
|
+
### Sessions and turns
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
Agent(session="new") # fresh session
|
|
291
|
+
Agent(session="latest") # newest saved session
|
|
292
|
+
Agent(session="<session_id>") # specific saved session
|
|
293
|
+
Agent(session="/path/to/session.json") # session file
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
By default, a turn runs until the agent has completed its tool/model loop. `auto_proceed=False` is an advanced mode for external orchestration: your application can pause after each model step, inspect state, approve or cancel work, and resume explicitly.
|
|
297
|
+
|
|
298
|
+
```python
|
|
299
|
+
agent = Agent(session="new", auto_proceed=False)
|
|
300
|
+
turn = agent("Please explore the current repo. Use tools if needed.")
|
|
301
|
+
|
|
302
|
+
while not turn.completed and turn.reason == "requires_next_step":
|
|
303
|
+
# External monitoring, approval, logging, cancellation, etc. can happen here.
|
|
304
|
+
turn = agent.resume_turn(turn)
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Extending the agent
|
|
308
|
+
|
|
309
|
+
Use runtime extensions when you want to customize an installed agent without forking the repository.
|
|
310
|
+
|
|
311
|
+
At startup, the agent scans:
|
|
312
|
+
|
|
313
|
+
```text
|
|
314
|
+
~/.codex-agent/plugins/*.py
|
|
315
|
+
~/.codex-agent/commands/*.py
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Files starting with `_` are ignored.
|
|
319
|
+
|
|
320
|
+
A plugin module may expose:
|
|
321
|
+
|
|
322
|
+
- a `Plugin` subclass;
|
|
323
|
+
- a `register(agent)` function;
|
|
324
|
+
- decorated `@tool`, `@provider`, or `@command` callables for small extensions.
|
|
325
|
+
|
|
326
|
+
Direct runtime `tools/` and `providers/` folders are intentionally not loaded. Put simple runtime tools/providers in a plugin module, or use `agent.add_tool()` and `agent.add_provider()` in SDK code.
|
|
327
|
+
|
|
328
|
+
### Plugin example
|
|
329
|
+
|
|
330
|
+
```python
|
|
331
|
+
from codex_agent import Agent, Plugin, provider, tool
|
|
332
|
+
|
|
333
|
+
class ProjectNotesPlugin(Plugin):
|
|
334
|
+
name = "project_notes"
|
|
335
|
+
system_prompt = "# Project Notes\nUse project notes when relevant."
|
|
336
|
+
|
|
337
|
+
def __init__(self, agent):
|
|
338
|
+
super().__init__(agent)
|
|
339
|
+
self.notes = []
|
|
340
|
+
|
|
341
|
+
@tool
|
|
342
|
+
def remember_note(self, note: str):
|
|
343
|
+
"""
|
|
344
|
+
description: Store a project note that should be available in later turns.
|
|
345
|
+
parameters:
|
|
346
|
+
note:
|
|
347
|
+
type: string
|
|
348
|
+
description: The note to remember. Keep it concise and project-specific.
|
|
349
|
+
required:
|
|
350
|
+
- note
|
|
351
|
+
"""
|
|
352
|
+
self.notes.append(note)
|
|
353
|
+
return f"Stored {len(self.notes)} note(s)."
|
|
354
|
+
|
|
355
|
+
@provider
|
|
356
|
+
def project_notes(self):
|
|
357
|
+
if not self.notes:
|
|
358
|
+
return None
|
|
359
|
+
return "Project notes:\n" + "\n".join(f"- {note}" for note in self.notes)
|
|
360
|
+
|
|
361
|
+
agent = Agent(session="latest")
|
|
362
|
+
agent.add_plugin(ProjectNotesPlugin(agent))
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Runtime plugin example
|
|
366
|
+
|
|
367
|
+
`~/.codex-agent/plugins/git_helpers.py`:
|
|
368
|
+
|
|
369
|
+
```python
|
|
370
|
+
from datetime import datetime
|
|
371
|
+
from zoneinfo import ZoneInfo
|
|
372
|
+
import subprocess
|
|
373
|
+
from codex_agent import provider, tool
|
|
374
|
+
|
|
375
|
+
@tool
|
|
376
|
+
def current_branch() -> str:
|
|
377
|
+
"""Return the current git branch."""
|
|
378
|
+
return subprocess.check_output(
|
|
379
|
+
["git", "branch", "--show-current"],
|
|
380
|
+
text=True,
|
|
381
|
+
).strip()
|
|
382
|
+
|
|
383
|
+
@provider
|
|
384
|
+
def current_time():
|
|
385
|
+
now = datetime.now(ZoneInfo("Europe/Paris"))
|
|
386
|
+
return f"Current local time: {now:%Y-%m-%d %H:%M:%S %Z}"
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
`~/.codex-agent/commands/repo.py`:
|
|
390
|
+
|
|
391
|
+
```python
|
|
392
|
+
from codex_agent import command, get_agent
|
|
393
|
+
|
|
394
|
+
@command(name="repo")
|
|
395
|
+
def repo(args=""):
|
|
396
|
+
agent = get_agent()
|
|
397
|
+
return f"session={agent.current_session_id}; args={args}"
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Events and hooks
|
|
401
|
+
|
|
402
|
+
`Agent` exposes an event bus for UIs, automation, and plugins:
|
|
403
|
+
|
|
404
|
+
```python
|
|
405
|
+
from codex_agent import Agent, MessageAddedEvent, ToolCallStartEvent
|
|
406
|
+
|
|
407
|
+
agent = Agent(session="new")
|
|
408
|
+
|
|
409
|
+
@agent.on(MessageAddedEvent)
|
|
410
|
+
def log_message(event):
|
|
411
|
+
print("message", event.message.type)
|
|
412
|
+
|
|
413
|
+
@agent.on(ToolCallStartEvent)
|
|
414
|
+
def log_tool(event):
|
|
415
|
+
print("tool", event.name)
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
Plugins and tools may also emit custom events and expose custom hook points:
|
|
419
|
+
|
|
420
|
+
```python
|
|
421
|
+
from codex_agent import Agent, Event, Plugin, tool
|
|
422
|
+
|
|
423
|
+
class NoteStoredEvent(Event):
|
|
424
|
+
note = ""
|
|
425
|
+
|
|
426
|
+
class NotesPlugin(Plugin):
|
|
427
|
+
name = "notes"
|
|
428
|
+
|
|
429
|
+
@tool
|
|
430
|
+
def remember_note(self, note: str):
|
|
431
|
+
"""
|
|
432
|
+
description: Store a note and notify listeners.
|
|
433
|
+
parameters:
|
|
434
|
+
note:
|
|
435
|
+
type: string
|
|
436
|
+
description: Note to store.
|
|
437
|
+
required:
|
|
438
|
+
- note
|
|
439
|
+
"""
|
|
440
|
+
context = self.agent.run_hook("notes.before_store", note=note)
|
|
441
|
+
if context.stopped:
|
|
442
|
+
return "Note rejected."
|
|
443
|
+
note = context.payload.note
|
|
444
|
+
self.agent.emit(NoteStoredEvent, note=note)
|
|
445
|
+
return "Note stored."
|
|
446
|
+
|
|
447
|
+
agent = Agent(session="new")
|
|
448
|
+
agent.add_plugin(NotesPlugin(agent))
|
|
449
|
+
|
|
450
|
+
@agent.on(NoteStoredEvent)
|
|
451
|
+
def log_note(event):
|
|
452
|
+
print("stored note:", event.note)
|
|
453
|
+
|
|
454
|
+
@agent.add_hook("notes.before_store")
|
|
455
|
+
def trim_note(context):
|
|
456
|
+
context.payload.note = context.payload.note.strip()
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
Plugin methods can also subscribe declaratively with `@event_handler(...)` and `@hook_handler(...)`.
|
|
460
|
+
|
|
461
|
+
## Built-in capabilities
|
|
462
|
+
|
|
463
|
+
The default agent includes practical local tools grouped as plugins:
|
|
464
|
+
|
|
465
|
+
| Area | Examples | Purpose |
|
|
466
|
+
| --- | --- | --- |
|
|
467
|
+
| Files | `read`, `view`, `write`, `edit` | Strict text reads, broad extraction, exact-string edits. |
|
|
468
|
+
| Shell | `bash`, `python` | Shell commands and persistent Python execution. |
|
|
469
|
+
| Memory | `memory_add`, `memory_search`, `/memory_config` | Durable semantic memory and retrieval context. |
|
|
470
|
+
| Planner | `planner_create`, `planner_check` | Persistent named todos surfaced as context. |
|
|
471
|
+
| Scheduler | `scheduler_schedule`, `scheduler_restart_and_wakeup` | Future turns and post-restart continuation. |
|
|
472
|
+
| Browser | `browser_open`, `browser_click`, `browser_fill` | Persistent Playwright/Chromium automation. |
|
|
473
|
+
| Desktop | `desktop_start_session`, `desktop_run_commands` | Screenshot-backed Linux desktop automation. |
|
|
474
|
+
| Subagents | `subagents_run` | Ephemeral child agents from predefined profiles. |
|
|
475
|
+
|
|
476
|
+
Current built-in plugin modules include `files`, `content`, `bash`, `python`, `interface`, `environment`, `memory`, `planner`, `scheduler`, `browser`, `desktop`, and `subagents`.
|
|
477
|
+
|
|
478
|
+
The `subagents` plugin ships an `explorer` profile: a read-only codebase inspection agent.
|
|
479
|
+
|
|
480
|
+
Select built-ins explicitly when you want a smaller agent:
|
|
481
|
+
|
|
482
|
+
```python
|
|
483
|
+
agent = Agent(
|
|
484
|
+
session="latest",
|
|
485
|
+
builtin_plugins=["files", "content", "bash", "python", "memory", "planner"],
|
|
486
|
+
)
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
`None` loads all built-ins, `[]` loads none, and an explicit list selects plugin module names.
|
|
490
|
+
|
|
491
|
+
## Running modes
|
|
492
|
+
|
|
493
|
+
You can ignore this section for normal TUI usage. It is for services, automation, and integrations.
|
|
494
|
+
|
|
495
|
+
| Mode | Entry point | Best for |
|
|
496
|
+
| --- | --- | --- |
|
|
497
|
+
| Embedded Python | `Agent(...)` | Scripts, notebooks, tests, custom applications. |
|
|
498
|
+
| Interactive TUI | `codex-agent` | Daily local assistant usage. |
|
|
499
|
+
| Persistent server | `codex-agent start server` | Long-lived local service used by UIs or scripts. |
|
|
500
|
+
| Headless CLI | `codex-agent run ...` | Automation and shell pipelines. |
|
|
501
|
+
| Process runtime | `codex-agent run --runtime process ...` | One-shot isolated runs without an existing server. |
|
|
502
|
+
| Tray/service setup | `codex-agent bootstrap` | Desktop availability independent of a terminal. |
|
|
503
|
+
|
|
504
|
+
Run a persistent background server:
|
|
505
|
+
|
|
506
|
+
```bash
|
|
507
|
+
codex-agent start server
|
|
508
|
+
codex-agent open tui
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
Detached logs are written under `~/.codex-agent/logs/server.log`.
|
|
512
|
+
|
|
513
|
+
Useful headless commands:
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
codex-agent status --json
|
|
517
|
+
codex-agent tools
|
|
518
|
+
codex-agent config get model
|
|
519
|
+
codex-agent run "Run a quick repository health check."
|
|
520
|
+
git diff -- README.md | codex-agent run --stdin "Review this documentation diff."
|
|
521
|
+
codex-agent run --runtime process "Summarize the current project layout."
|
|
522
|
+
codex-agent interrupt "user changed priority"
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
The local server exposes FastAPI REST/SSE endpoints for health, status, sessions, config, messages, tools, wakeups, live events, replay, turns, interrupts, and restart. The TUI uses SSE, tracks event cursors, replays the latest turn when opened mid-session, and reconnects after server restarts or transient stream loss.
|
|
526
|
+
|
|
527
|
+
## Configuration and runtime files
|
|
528
|
+
|
|
529
|
+
Configure `Agent` directly:
|
|
530
|
+
|
|
531
|
+
```python
|
|
532
|
+
from codex_agent import Agent
|
|
533
|
+
|
|
534
|
+
agent = Agent(
|
|
535
|
+
session="latest",
|
|
536
|
+
model="gpt-5.5",
|
|
537
|
+
reasoning_effort="medium",
|
|
538
|
+
verbosity="medium",
|
|
539
|
+
input_token_limit=128000,
|
|
540
|
+
auto_compact=True,
|
|
541
|
+
web_search_enabled=False,
|
|
542
|
+
image_generation_enabled=False,
|
|
543
|
+
builtin_plugins=None, # None = all, [] = none, or explicit plugin names
|
|
544
|
+
custom_plugins=None, # None = all runtime plugins, [] = none
|
|
545
|
+
)
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
Or update saved config from the CLI:
|
|
549
|
+
|
|
550
|
+
```bash
|
|
551
|
+
codex-agent config get
|
|
552
|
+
codex-agent config set input_token_limit 128000
|
|
553
|
+
codex-agent config set voice_enabled=true
|
|
554
|
+
codex-agent config set builtin_plugins='["memory", "planner", "scheduler"]'
|
|
555
|
+
codex-agent config set --no-save verbosity low
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
Saved local state lives in `~/.codex-agent` by default:
|
|
559
|
+
|
|
560
|
+
```text
|
|
561
|
+
sessions/ persisted conversation histories as JSON
|
|
562
|
+
workfolder/ generated or uploaded working files
|
|
563
|
+
plugins/ user runtime plugins
|
|
564
|
+
commands/ user runtime slash commands
|
|
565
|
+
browser/ persistent browser profiles and screenshots
|
|
566
|
+
logs/ detached server/tray logs
|
|
567
|
+
memory.json durable semantic memory entries
|
|
568
|
+
planner.json persistent named todos
|
|
569
|
+
wakeups.json scheduled autonomous wakeups
|
|
570
|
+
agent_config.json persisted runtime configuration
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
Override it with:
|
|
574
|
+
|
|
575
|
+
```bash
|
|
576
|
+
AGENT_RUNTIME_DIR=/tmp/my-codex-agent-runtime codex-agent
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
## Development
|
|
580
|
+
|
|
581
|
+
Project layout:
|
|
582
|
+
|
|
583
|
+
```text
|
|
584
|
+
codex_agent/ Python package
|
|
585
|
+
codex_agent/agent.py Central Agent object and high-level public methods
|
|
586
|
+
codex_agent/mainloop.py Turn loop, assistant calls, tool execution, pending results
|
|
587
|
+
codex_agent/stream.py SDK event stream wrapper around an AgentFuture
|
|
588
|
+
codex_agent/context.py Context assembly and token budgeting
|
|
589
|
+
codex_agent/sessions.py Persistent sessions and compaction
|
|
590
|
+
codex_agent/tool.py Tool model, decorators, and manager
|
|
591
|
+
codex_agent/provider.py Provider decorator and manager
|
|
592
|
+
codex_agent/plugin.py Stateful plugin base class and manager
|
|
593
|
+
codex_agent/command.py Slash command registry and dispatch
|
|
594
|
+
codex_agent/hooks.py Generic runtime hook manager
|
|
595
|
+
codex_agent/event.py Event classes and event bus
|
|
596
|
+
codex_agent/server/ FastAPI REST/SSE bridge package
|
|
597
|
+
codex_agent/tui/ Textual TUI client
|
|
598
|
+
codex_agent/cli/ Root CLI and headless runners
|
|
599
|
+
codex_agent/builtin_plugins/ Built-in capabilities grouped as plugins
|
|
600
|
+
tests/ Test suite
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
Run checks:
|
|
604
|
+
|
|
605
|
+
```bash
|
|
606
|
+
python -m pyflakes codex_agent tests
|
|
607
|
+
python -m pytest
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
The current tree validates at:
|
|
611
|
+
|
|
612
|
+
```text
|
|
613
|
+
489 passed
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
Build distributions:
|
|
617
|
+
|
|
618
|
+
```bash
|
|
619
|
+
python -m pip install build twine
|
|
620
|
+
rm -rf build dist *.egg-info
|
|
621
|
+
python -m build
|
|
622
|
+
python -m twine check dist/*
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
## Recent releases
|
|
626
|
+
|
|
627
|
+
- `0.1.23`: add SDK event streaming with `Agent.stream()`, root `Agent.add_plugin()`, a faster README flow, the `~/.codex-agent` runtime default, text-first voice defaults, safer prompt templating limited to system messages, smarter `codex-agent` local-server attachment, and clearer TUI tool-call progress lines.
|
|
628
|
+
- `0.1.22`: harden FastAPI/SSE and TUI streaming after a stabilization audit; add finite SSE read timeouts, stale-subscriber shutdown, persisted turn-event locking, synchronous replay delta flushes, process-runtime startup guards, isolated event handlers, and shared version metadata.
|
|
629
|
+
- `0.1.21`: add structured `AgentTurn` returns with messages/events, resumable non-terminal turns for `auto_proceed=False`, profile-based subagents, hierarchical message/event types, and internal wakeups as developer messages.
|
|
630
|
+
- `0.1.20`: make runtime plugins the user-facing extension unit for tools/providers/commands, remove legacy direct runtime tool/provider loading, split tool/provider managers, and keep system-prompt templating on an explicit minimal namespace.
|
|
631
|
+
|
|
632
|
+
See [`CHANGELOG.md`](CHANGELOG.md) for the full history.
|
|
633
|
+
|
|
634
|
+
## Safety notes
|
|
635
|
+
|
|
636
|
+
This project lets an AI assistant act on the local machine. That is useful, but risky.
|
|
637
|
+
|
|
638
|
+
Recommended practices:
|
|
639
|
+
|
|
640
|
+
- Use a dedicated runtime directory for experiments.
|
|
641
|
+
- Review tool calls before enabling autonomous workflows.
|
|
642
|
+
- Avoid running the agent with elevated privileges.
|
|
643
|
+
- Keep secrets out of prompts, logs, committed runtime files, and shared session exports.
|
|
644
|
+
- Treat browser and desktop automation as real user actions.
|
|
645
|
+
- Keep important runtime plugins under version control.
|
|
646
|
+
|
|
647
|
+
## License
|
|
648
|
+
|
|
649
|
+
MIT. See [LICENSE](LICENSE).
|