agent-readable 0.1.1__tar.gz → 0.2.0__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.
- {agent_readable-0.1.1 → agent_readable-0.2.0}/.github/workflows/test.yml +17 -0
- agent_readable-0.2.0/CHANGELOG.md +73 -0
- {agent_readable-0.1.1 → agent_readable-0.2.0}/PKG-INFO +106 -95
- {agent_readable-0.1.1 → agent_readable-0.2.0}/README.md +103 -93
- {agent_readable-0.1.1 → agent_readable-0.2.0}/docs/agent_help_vs_help.gif +0 -0
- {agent_readable-0.1.1 → agent_readable-0.2.0}/examples/any_class.py +7 -6
- {agent_readable-0.1.1 → agent_readable-0.2.0}/examples/duck_type.py +2 -2
- {agent_readable-0.1.1 → agent_readable-0.2.0}/examples/modules_and_functions.py +1 -1
- {agent_readable-0.1.1 → agent_readable-0.2.0}/examples/sqlite_connection.py +2 -2
- {agent_readable-0.1.1 → agent_readable-0.2.0}/examples/temperature.py +2 -2
- {agent_readable-0.1.1 → agent_readable-0.2.0}/pyproject.toml +15 -3
- {agent_readable-0.1.1 → agent_readable-0.2.0}/src/agent_readable/__init__.py +1 -1
- agent_readable-0.2.0/src/agent_readable/_model.py +301 -0
- agent_readable-0.2.0/src/agent_readable/_protocol.py +194 -0
- agent_readable-0.2.0/src/agent_readable/_render.py +64 -0
- agent_readable-0.2.0/tests/__init__.py +0 -0
- {agent_readable-0.1.1 → agent_readable-0.2.0}/tests/test_cli.py +1 -1
- {agent_readable-0.1.1 → agent_readable-0.2.0}/tests/test_protocol.py +198 -4
- agent_readable-0.1.1/AGENT-PROMPT.md +0 -82
- agent_readable-0.1.1/src/agent_readable/_protocol.py +0 -417
- {agent_readable-0.1.1 → agent_readable-0.2.0}/.github/workflows/publish.yml +0 -0
- {agent_readable-0.1.1 → agent_readable-0.2.0}/.gitignore +0 -0
- {agent_readable-0.1.1 → agent_readable-0.2.0}/LICENSE +0 -0
- {agent_readable-0.1.1 → agent_readable-0.2.0}/src/agent_readable/__main__.py +0 -0
- /agent_readable-0.1.1/tests/__init__.py → /agent_readable-0.2.0/src/agent_readable/py.typed +0 -0
|
@@ -7,6 +7,23 @@ on:
|
|
|
7
7
|
workflow_dispatch:
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Install uv
|
|
16
|
+
uses: astral-sh/setup-uv@v3
|
|
17
|
+
|
|
18
|
+
- name: Install dev deps
|
|
19
|
+
run: uv sync --group dev
|
|
20
|
+
|
|
21
|
+
- name: Ruff check
|
|
22
|
+
run: uv run ruff check
|
|
23
|
+
|
|
24
|
+
- name: Ruff format check
|
|
25
|
+
run: uv run ruff format --check
|
|
26
|
+
|
|
10
27
|
test:
|
|
11
28
|
runs-on: ubuntu-latest
|
|
12
29
|
strategy:
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.2] - 2026-05-30
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `py.typed` marker so inline type annotations are visible to downstream type
|
|
15
|
+
checkers (PEP 561).
|
|
16
|
+
- A module's `__all__` is now honored as the authoritative public API when
|
|
17
|
+
present, including symbols re-exported from other modules.
|
|
18
|
+
- `agent_help()` now emits a `UserWarning` when a class defines both a custom
|
|
19
|
+
`__agent_help__()` and `__agent_notes__()`, since the notes are silently
|
|
20
|
+
dropped in that case.
|
|
21
|
+
- Agent Skill at `skills/agent-readable/SKILL.md` following the
|
|
22
|
+
[Agent Skills open standard](https://agentskills.io). Installable via
|
|
23
|
+
`npx skills add zydo/agent-readable --skill agent-readable` and portable
|
|
24
|
+
across Claude Code, Codex CLI (OpenAI), Gemini CLI (Google), GitHub Copilot,
|
|
25
|
+
Cursor, JetBrains Junie, Goose, OpenCode, and 40+ other adopters. The skill
|
|
26
|
+
teaches the agent to call `agent_help()` before writing Python against a
|
|
27
|
+
library and to author new APIs with `__agent_notes__()`. Supersedes
|
|
28
|
+
`AGENT-PROMPT.md` as the recommended way to wire up coding agents.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- Method signatures with a positional-only `self` no longer render a dangling
|
|
33
|
+
`/` (e.g. `backup(/, target)` now renders as `backup(target)`).
|
|
34
|
+
|
|
35
|
+
### Documentation
|
|
36
|
+
|
|
37
|
+
- README and examples reframed around curation, not compactness. The "Why it
|
|
38
|
+
matters" section now leads with two failure modes — what-exists (curated
|
|
39
|
+
Public API list curbs hallucinated methods and stale signatures) and
|
|
40
|
+
how-to-use (lifecycle rules via `__agent_notes__()`) — instead of a
|
|
41
|
+
comparative empirical claim about which is more common. Removed the
|
|
42
|
+
"217 vs 56 lines" framing in favor of structure-and-rules language.
|
|
43
|
+
- Tagline sharpened to lead with the hallucination-stopping outcome rather
|
|
44
|
+
than the protocol mechanics.
|
|
45
|
+
|
|
46
|
+
### Removed
|
|
47
|
+
|
|
48
|
+
- `AGENT-PROMPT.md` (superseded by the agent skill at
|
|
49
|
+
`skills/agent-readable/SKILL.md`).
|
|
50
|
+
|
|
51
|
+
## [0.1.1] - 2026-05-11
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- `agent_help()` support for functions and methods.
|
|
56
|
+
|
|
57
|
+
### Documentation
|
|
58
|
+
|
|
59
|
+
- Demo GIF comparing `agent_help()` and `help()`, plus additional README
|
|
60
|
+
examples.
|
|
61
|
+
|
|
62
|
+
## [0.1.0] - 2026-05-10
|
|
63
|
+
|
|
64
|
+
### Added
|
|
65
|
+
|
|
66
|
+
- Initial release: the `agent_help()` function, the `AgentReadable` protocol,
|
|
67
|
+
`AgentReadableMixin`, `__agent_notes__` accumulation across the MRO, module
|
|
68
|
+
support, and the `python -m agent_readable` CLI.
|
|
69
|
+
|
|
70
|
+
[Unreleased]: https://github.com/zydo/agent-readable/compare/v0.1.2...HEAD
|
|
71
|
+
[0.1.2]: https://github.com/zydo/agent-readable/compare/v0.1.1...v0.1.2
|
|
72
|
+
[0.1.1]: https://github.com/zydo/agent-readable/compare/v0.1.0...v0.1.1
|
|
73
|
+
[0.1.0]: https://github.com/zydo/agent-readable/releases/tag/v0.1.0
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-readable
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: A lightweight Python protocol for agent-oriented documentation
|
|
5
5
|
Project-URL: Repository, https://github.com/zydo/agent-readable
|
|
6
|
+
Project-URL: Issues, https://github.com/zydo/agent-readable/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/zydo/agent-readable/blob/main/CHANGELOG.md
|
|
6
8
|
Author: zydo and agent-readable contributors
|
|
7
9
|
License-Expression: MIT
|
|
8
10
|
License-File: LICENSE
|
|
9
11
|
Keywords: agent,agent-help,ai,ai-agent,coding-agent,context-engineering,docstring,documentation,llm,mixin,prompt-engineering,protocol,vibe-coding
|
|
10
12
|
Classifier: Development Status :: 3 - Alpha
|
|
11
13
|
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
13
14
|
Classifier: Programming Language :: Python :: 3
|
|
14
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -26,7 +27,13 @@ Description-Content-Type: text/markdown
|
|
|
26
27
|
|
|
27
28
|
# agent-readable
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
Stop coding agents from hallucinating Python APIs. `agent_help(target)` reads the live public-API surface off any class, module, function, or method — no author opt-in needed — and optionally returns class-level usage rules (lifecycle order, pre-conditions, anti-patterns) when the library ships them.
|
|
31
|
+
|
|
32
|
+
To let your coding agent automatically call `agent_help()` before using an unfamiliar API, install the skill:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx skills add zydo/skills --skill agent-readable
|
|
36
|
+
```
|
|
30
37
|
|
|
31
38
|
<!-- markdownlint-disable MD033 -->
|
|
32
39
|
<p align="center">
|
|
@@ -39,16 +46,9 @@ A lightweight Python protocol for exposing agent-oriented documentation from cla
|
|
|
39
46
|
|
|
40
47
|
AI coding agents recognize established libraries from their training data, but they hallucinate when APIs change, when libraries are new, or when correct usage depends on rules that aren't visible from the API surface — pre-conditions, lifecycle order, anti-patterns, *"use `call()` for non-streaming, `stream()` for streaming."*
|
|
41
48
|
|
|
42
|
-
Today there's nowhere to put those rules where an agent will reliably find them. Docstrings document the API surface, not behavioral rules. `AGENTS.md` and `llms.txt` work at project granularity, drift fast, and don't travel with refactors. `help()`
|
|
43
|
-
|
|
44
|
-
`agent-readable` adds two dunders — `__agent_help__` (full custom output) and `__agent_notes__` (additive guidance that accumulates across inheritance) — that live next to the code. Library authors annotate once; any agent that calls `agent_help(cls)` gets the rules.
|
|
49
|
+
Today there's nowhere to put those rules where an agent will reliably find them. Docstrings document the API surface, not behavioral rules. `AGENTS.md` and `llms.txt` work at project granularity, drift fast, and don't travel with refactors. `help()` only describes interfaces — and mixes inherited dunders and MRO detail in with the methods you actually want to use.
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
help(logging.Logger) 217 lines — every inherited method, dunder, and MRO detail.
|
|
48
|
-
agent_help(logging.Logger) 56 lines — structured sections + any author notes.
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
The compactness is a side effect; the structure is the point.
|
|
51
|
+
`agent-readable` has two halves, and the lighter one stands alone. The **consume side** is one function — `agent_help(target)` — that works on every Python library today, annotated or not. It introspects the live, installed class/module/function and returns a curated public-API list with current signatures, no inherited-dunder or MRO noise to wade through. That alone closes the *what exists* hallucination — agents stop inventing methods that aren't there and stop calling real ones with stale signatures. The **author side** adds two dunders: `__agent_help__` for full custom output and `__agent_notes__` for additive behavioral rules that accumulate across inheritance. When a library opts in, those rules show up next to the public-API list in the same `agent_help()` output — so the rules travel with refactors instead of rotting in a sidecar file.
|
|
52
52
|
|
|
53
53
|
## Installation
|
|
54
54
|
|
|
@@ -60,11 +60,51 @@ Requires Python 3.10+. No runtime dependencies.
|
|
|
60
60
|
|
|
61
61
|
## Quickstart
|
|
62
62
|
|
|
63
|
+
`agent_help()` works on **any Python class, module, function, or method — no opt-in required**. Point it at a stdlib class:
|
|
64
|
+
|
|
63
65
|
```python
|
|
64
|
-
from agent_readable import
|
|
66
|
+
from agent_readable import agent_help
|
|
67
|
+
import logging
|
|
65
68
|
|
|
69
|
+
print(agent_help(logging.Logger))
|
|
70
|
+
```
|
|
66
71
|
|
|
67
|
-
|
|
72
|
+
Output (excerpted):
|
|
73
|
+
|
|
74
|
+
````
|
|
75
|
+
# Logger
|
|
76
|
+
|
|
77
|
+
## Constructor
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
Logger(name, level=0)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Purpose
|
|
84
|
+
|
|
85
|
+
Instances of the Logger class represent a single logging channel. ...
|
|
86
|
+
|
|
87
|
+
## Public API
|
|
88
|
+
|
|
89
|
+
- `addHandler(hdlr)` method: Add the specified handler to this logger.
|
|
90
|
+
- `debug(msg, *args, **kwargs)` method: Log 'msg % args' with severity 'DEBUG'.
|
|
91
|
+
- `info(msg, *args, **kwargs)` method: Log 'msg % args' with severity 'INFO'.
|
|
92
|
+
- `setLevel(level)` method: Set the logging level of this logger.
|
|
93
|
+
- `warning(msg, *args, **kwargs)` method: Log 'msg % args' with severity 'WARNING'.
|
|
94
|
+
- ...
|
|
95
|
+
````
|
|
96
|
+
|
|
97
|
+
The `## Public API` list comes from **runtime introspection of the live, installed version** — current signatures, no inherited-dunder noise, no stale training-data guesses. Substitute any class, module, function, or method (yours, a third party's, or a stdlib one); zero setup on the target side.
|
|
98
|
+
|
|
99
|
+
### Library authors: ship usage rules next to the code (optional)
|
|
100
|
+
|
|
101
|
+
When you own the class, you can also ship class-level usage rules — lifecycle order, pre-conditions, anti-patterns — that `agent_help()` returns alongside the auto-generated public-API list. Define a `__agent_notes__()` classmethod (no mixin, no inheritance required); notes accumulate across the MRO so subclasses don't lose parent rules:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from agent_readable import agent_help
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class Sensor:
|
|
68
108
|
"""Reads a value from a hardware sensor."""
|
|
69
109
|
|
|
70
110
|
def __init__(self, pin: int, *, unit: str = "C"): ...
|
|
@@ -91,52 +131,19 @@ class Sensor(AgentReadableMixin):
|
|
|
91
131
|
print(agent_help(Sensor))
|
|
92
132
|
```
|
|
93
133
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
````
|
|
97
|
-
# Sensor
|
|
98
|
-
|
|
99
|
-
## Constructor
|
|
100
|
-
|
|
101
|
-
```python
|
|
102
|
-
Sensor(pin: int, *, unit: str = 'C')
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Purpose
|
|
106
|
-
|
|
107
|
-
Reads a value from a hardware sensor.
|
|
108
|
-
|
|
109
|
-
## Public API
|
|
110
|
-
|
|
111
|
-
- `calibrate(offset: float)` method: Apply a calibration offset.
|
|
112
|
-
- `read() -> float` method: Read the current sensor value.
|
|
113
|
-
|
|
114
|
-
## Agent usage rules
|
|
115
|
-
|
|
116
|
-
- Prefer the public API listed above.
|
|
117
|
-
- Do not use private methods or attributes starting with `_`.
|
|
118
|
-
- Do not invent unsupported behavior.
|
|
119
|
-
- If usage is ambiguous, prefer the simplest documented usage pattern.
|
|
120
|
-
|
|
121
|
-
## Notes from class Sensor
|
|
122
|
-
|
|
123
|
-
## Do
|
|
124
|
-
|
|
125
|
-
- Call `calibrate()` once during setup, before `read()`.
|
|
126
|
-
|
|
127
|
-
## Do not
|
|
128
|
-
|
|
129
|
-
- Do not call `read()` before `calibrate()` on first use.
|
|
130
|
-
````
|
|
134
|
+
`agent_help(Sensor)` now returns the same auto-generated public-API list, plus a `## Notes from class Sensor` section carrying the rules above. Full output and inheritance-with-notes behavior in [Example 2](#example-2-inheritance-with-accumulated-notes) below.
|
|
131
135
|
|
|
132
136
|
## Why it matters
|
|
133
137
|
|
|
134
|
-
`
|
|
138
|
+
`agent_help()` covers two failure modes agents hit on real APIs:
|
|
135
139
|
|
|
136
|
-
`
|
|
140
|
+
1. **What exists.** The `## Public API` section is a curated list of current signatures pulled from runtime introspection — no hallucinated methods, no stale signatures from training data, no private members leaking in. If the agent reads this list first, it stops inventing methods that don't exist and stops calling real ones with the wrong arguments.
|
|
141
|
+
2. **How to use it correctly.** Lifecycle order, pre-conditions, anti-patterns, *"this method is for X, that one for Y."* These don't fit in any single method's docstring and don't belong in a project-level `AGENTS.md` (which describes whole repos). They're class-level, and they need to travel with refactors. `__agent_notes__()` gives them a home next to the code.
|
|
142
|
+
|
|
143
|
+
A concrete contrast:
|
|
137
144
|
|
|
138
145
|
```
|
|
139
|
-
# help(sqlite3.Connection) —
|
|
146
|
+
# help(sqlite3.Connection) — every inherited dunder, in source order:
|
|
140
147
|
Help on class Connection in module sqlite3:
|
|
141
148
|
|
|
142
149
|
class Connection(builtins.object)
|
|
@@ -150,12 +157,13 @@ class Connection(builtins.object)
|
|
|
150
157
|
| ...
|
|
151
158
|
| backup(self, target, /, *, pages=-1, progress=None, ...)
|
|
152
159
|
| blobopen(self, table, column, rowid, /, *, readonly=False, ...)
|
|
153
|
-
| ... (
|
|
160
|
+
| ... (no curation, no behavioral rules, no signal that backup() needs an
|
|
161
|
+
| open target connection before being called)
|
|
154
162
|
```
|
|
155
163
|
|
|
156
|
-
`agent_help(sqlite3.Connection)` produces a
|
|
164
|
+
`agent_help(sqlite3.Connection)` produces a curated public-API list with current signatures and any class-level rules attached — see Example 1 below. Notes from `__agent_notes__()` accumulate across inheritance. Class docs travel with the code in commits, reviews, and refactors. Drift gets caught in code review, not weeks later in a sidecar file.
|
|
157
165
|
|
|
158
|
-
The examples below demonstrate
|
|
166
|
+
The examples below demonstrate five ways to use `agent_help()`, three with library-author opt-in (Examples 1–3) and two on plain classes/modules with no setup (Examples 4–5).
|
|
159
167
|
|
|
160
168
|
## Example 1: Wrapping an existing class
|
|
161
169
|
|
|
@@ -190,14 +198,14 @@ An agent-friendly wrapper around sqlite3.Connection.
|
|
|
190
198
|
|
|
191
199
|
## Public API
|
|
192
200
|
|
|
193
|
-
- `backup(
|
|
201
|
+
- `backup(target, *, pages=-1, progress=None, name='main', sleep=0.25)` method: Makes a backup of the database.
|
|
194
202
|
- ...
|
|
195
|
-
- `close(
|
|
196
|
-
- `commit(
|
|
203
|
+
- `close()` method: Close the database connection.
|
|
204
|
+
- `commit()` method: Commit any pending transaction to the database.
|
|
197
205
|
- ...
|
|
198
206
|
- `execute(...)` method: Executes an SQL statement.
|
|
199
207
|
- ...
|
|
200
|
-
- `rollback(
|
|
208
|
+
- `rollback()` method: Roll back to the start of any pending transaction.
|
|
201
209
|
- ...
|
|
202
210
|
|
|
203
211
|
## Agent usage rules
|
|
@@ -366,7 +374,7 @@ print(agent_help(RateLimiter))
|
|
|
366
374
|
|
|
367
375
|
## Example 4: Any class — no setup required
|
|
368
376
|
|
|
369
|
-
Even without the mixin or duck-typing, `agent_help()` still generates
|
|
377
|
+
Even without the mixin or duck-typing, `agent_help()` still generates structured Markdown from introspection — a curated public-API list with current signatures, free of inherited dunders and MRO clutter. If the class (or any class in its MRO) defines `__agent_notes__()`, those notes are auto-appended too — no mixin required.
|
|
370
378
|
Full example: [`examples/any_class.py`](examples/any_class.py).
|
|
371
379
|
|
|
372
380
|
```python
|
|
@@ -376,7 +384,7 @@ from agent_readable import agent_help
|
|
|
376
384
|
print(agent_help(logging.Logger))
|
|
377
385
|
```
|
|
378
386
|
|
|
379
|
-
`
|
|
387
|
+
Compare what `agent_help(logging.Logger)` returns to what `help(logging.Logger)` does — the former lists only the public methods you'd actually call, with their current signatures and docstring summaries:
|
|
380
388
|
|
|
381
389
|
````
|
|
382
390
|
# Logger
|
|
@@ -429,13 +437,15 @@ Output:
|
|
|
429
437
|
|
|
430
438
|
## Purpose
|
|
431
439
|
|
|
432
|
-
Example: Using agent_help() on modules.
|
|
440
|
+
Example: Using agent_help() on modules, functions, and methods.
|
|
433
441
|
|
|
434
|
-
Demonstrates
|
|
442
|
+
Demonstrates non-class targets:
|
|
435
443
|
1. A custom module (this file itself).
|
|
436
444
|
2. A stdlib module (pathlib).
|
|
445
|
+
3. A function (connect, defined below).
|
|
446
|
+
4. A method (Query.execute, defined below).
|
|
437
447
|
|
|
438
|
-
Run this file to see
|
|
448
|
+
Run this file to see all outputs:
|
|
439
449
|
python examples/modules_and_functions.py
|
|
440
450
|
|
|
441
451
|
## Public API
|
|
@@ -476,20 +486,13 @@ operating systems.
|
|
|
476
486
|
|
|
477
487
|
## Public API
|
|
478
488
|
|
|
479
|
-
- `DirEntryInfo` class: Implementation of pathlib.types.PathInfo that provides status
|
|
480
489
|
- `Path` class: PurePath subclass that can make system calls.
|
|
481
|
-
- `PathInfo` class: Implementation of pathlib.types.PathInfo that provides status
|
|
482
490
|
- `PosixPath` class: Path subclass for non-Windows systems.
|
|
483
491
|
- `PurePath` class: Base class for manipulating paths without I/O.
|
|
484
492
|
- `PurePosixPath` class: PurePath subclass for non-Windows systems.
|
|
485
493
|
- `PureWindowsPath` class: PurePath subclass for Windows systems.
|
|
486
494
|
- `UnsupportedOperation` class: An exception that is raised when an unsupported operation is attempted.
|
|
487
495
|
- `WindowsPath` class: Path subclass for Windows systems.
|
|
488
|
-
- `copy_info(info, target, follow_symlinks=True)` function: Copy metadata from the given PathInfo to the given local path.
|
|
489
|
-
- `copyfileobj(source_f, target_f)` function: Copy data from file-like object source_f to file-like object target_f.
|
|
490
|
-
- `ensure_different_files(source, target)` function: Raise OSError(EINVAL) if both paths refer to the same file.
|
|
491
|
-
- `ensure_distinct_paths(source, target)` function: Raise OSError(EINVAL) if the other path is within this path.
|
|
492
|
-
- `magic_open(path, mode='r', buffering=-1, encoding=None, errors=None, newline=None)` function: Open the file pointed to by this path and return a file object, as
|
|
493
496
|
|
|
494
497
|
## Agent usage rules
|
|
495
498
|
|
|
@@ -499,7 +502,7 @@ operating systems.
|
|
|
499
502
|
- If usage is ambiguous, prefer the simplest documented usage pattern.
|
|
500
503
|
````
|
|
501
504
|
|
|
502
|
-
Modules support less customization than classes — there is no mixin inheritance or `__agent_notes__()`. You can override the auto-generated output entirely by setting a module-level `__agent_help__` attribute (callable or string), but this is discouraged since it replaces the auto-generated summary — signatures, purpose, and public API listing are all lost. Prefer clear docstrings on the module and its functions/classes instead.
|
|
505
|
+
Modules support less customization than classes — there is no mixin inheritance or `__agent_notes__()`. You can override the auto-generated output entirely by setting a module-level `__agent_help__` attribute (callable or string), but this is discouraged since it replaces the auto-generated summary — signatures, purpose, and public API listing are all lost. Prefer clear docstrings on the module and its functions/classes instead. If the module defines `__all__`, that list is honored as the authoritative public API — including symbols re-exported from other modules.
|
|
503
506
|
|
|
504
507
|
You can also pass a function or method directly — `agent_help()` renders the signature, full docstring, and usage rules. The output is close to `help()` for a single callable; the bigger wins are still on classes and modules.
|
|
505
508
|
|
|
@@ -543,12 +546,13 @@ Outputs agent-oriented documentation for the given class, module, function, or m
|
|
|
543
546
|
|
|
544
547
|
### How does my agent know to call `agent_help()` instead of `help()`?
|
|
545
548
|
|
|
546
|
-
|
|
549
|
+
Install the companion agent skill:
|
|
547
550
|
|
|
548
|
-
|
|
549
|
-
|
|
551
|
+
```bash
|
|
552
|
+
npx skills add zydo/skills --skill agent-readable
|
|
553
|
+
```
|
|
550
554
|
|
|
551
|
-
|
|
555
|
+
The skill teaches the agent to install `agent-readable`, call `agent_help(target)` before writing code against a class, module, function, or method, and add `__agent_notes__()` (or improve docstrings) when authoring new public APIs. (Cursor is among the adopters too, but its skill integration is manual — you invoke the skill explicitly there rather than relying on description-match auto-activation.)
|
|
552
556
|
|
|
553
557
|
### How is this different from `AGENTS.md` / `llms.txt` / Cursor rules?
|
|
554
558
|
|
|
@@ -574,19 +578,23 @@ Yes. Two ways:
|
|
|
574
578
|
|
|
575
579
|
Yes — `agent_help()` falls back to introspection (Example 4). You get a structured summary of every plain class, mixin or not. Notes are added on top *if* the class defines them; otherwise the auto-doc is what you see.
|
|
576
580
|
|
|
581
|
+
### Is `agent_help()` the strongest fix for API hallucination?
|
|
582
|
+
|
|
583
|
+
No, and worth being upfront about it. The strongest known mitigation is **constrained decoding** at the harness or decoder layer — masking illegal API tokens before generation, so the model can't produce a nonexistent method at all. `agent_help()` takes the lighter, library-side path: an authoritative usage guide injected into the agent's context, leaving the agent to read and follow it. Recent research on Python API misuse shows the in-context route leaves a meaningful slice of hallucinations on the table even when verified API references are provided. The two approaches compose. Pick `agent_help()` when you have leverage on the library side and want a fix that works on every agent and every library today, without harness changes. Reach for constrained decoding when you control the harness or the decoder. Either way, verify generated code before merging.
|
|
584
|
+
|
|
577
585
|
## Keeping agent docs up to date
|
|
578
586
|
|
|
579
|
-
Agent docs can go stale when classes change — new methods, changed behavior, removed APIs.
|
|
587
|
+
Agent docs can go stale when classes change — new methods, changed behavior, removed APIs. Install the companion skill (`npx skills add zydo/skills --skill agent-readable`) to teach your agent to run `agent_help()` before modifying a class, prefer docstrings over `__agent_notes__()`, and verify that the output stays accurate after changes.
|
|
580
588
|
|
|
581
589
|
## The `__agent_help__` protocol
|
|
582
590
|
|
|
583
|
-
`__agent_help__()` is a dunder protocol, similar in spirit to
|
|
591
|
+
`__agent_help__()` is a dunder protocol for tool-specific documentation, similar in spirit to:
|
|
584
592
|
|
|
585
|
-
- `
|
|
586
|
-
- `__rich_repr__` (Rich) —
|
|
587
|
-
- `__html__` (Django, Jinja2) — HTML
|
|
588
|
-
|
|
589
|
-
|
|
593
|
+
- `__doc__` (Python `help()`, Sphinx, IDEs, REPLs) — the canonical "this is my human-readable documentation" slot, read by inspection tools and surfaced through `help()`
|
|
594
|
+
- `__rich_repr__` (Rich) — Rich-specific console representation read only when Rich renders the object
|
|
595
|
+
- `__html__` (Django, Jinja2, MarkupSafe) — HTML-renderer-specific representation read only when those template engines render the object
|
|
596
|
+
|
|
597
|
+
Unlike `__str__` or `__fspath__`, these dunders don't change Python runtime behavior — they're metadata slots a specific tool reads when it wants a representation. `__agent_help__` follows the same pattern for the agent-docs case.
|
|
590
598
|
|
|
591
599
|
Classes that define a `@classmethod` named `__agent_help__` returning a `str` are considered agent-readable. Modules can define a top-level `__agent_help__` attribute (callable or string). Call the top-level `agent_help(obj)` function to get the docs — just like `str()` calls `__str__()`. The `AgentReadable` `typing.Protocol` and `AgentReadableMixin` are provided for convenience and type-checking, but neither is required.
|
|
592
600
|
|
|
@@ -594,13 +602,15 @@ Classes that define a `@classmethod` named `__agent_help__` returning a `str` ar
|
|
|
594
602
|
|
|
595
603
|
The two dunders intentionally encode different composition rules:
|
|
596
604
|
|
|
597
|
-
| Aspect | `__agent_help__()` | `__agent_notes__()`
|
|
598
|
-
| --------------- | ----------------------------------------------- |
|
|
599
|
-
| Semantics | **Replacement** — returned string IS the output | **Additive** — appended to auto-generated docs
|
|
600
|
-
| Composition | Single class wins (the one closest in MRO) | Accumulated across the MRO; leaf class wins on conflict (header marks this)
|
|
601
|
-
| When to use | Total control over the rendered text | "Auto-doc + my extra do/don't rules"
|
|
602
|
-
| Skipped when | (always called if defined) |
|
|
603
|
-
| Mixin required? | No — duck-typed classmethod is enough | No — defining `__agent_notes__` on any class is enough
|
|
605
|
+
| Aspect | `__agent_help__()` | `__agent_notes__()` |
|
|
606
|
+
| --------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
607
|
+
| Semantics | **Replacement** — returned string IS the output | **Additive** — appended to auto-generated docs |
|
|
608
|
+
| Composition | Single class wins (the one closest in MRO) | Accumulated across the MRO; leaf class wins on conflict (header marks this) |
|
|
609
|
+
| When to use | Total control over the rendered text | "Auto-doc + my extra do/don't rules" |
|
|
610
|
+
| Skipped when | (always called if defined) | Silently dropped (with `UserWarning`) when a custom `__agent_help__` is present (it owns the output) |
|
|
611
|
+
| Mixin required? | No — duck-typed classmethod is enough | No — defining `__agent_notes__` on any class is enough |
|
|
612
|
+
|
|
613
|
+
**Heads up on the both-defined case.** When a class defines both `__agent_help__()` and `__agent_notes__()`, the notes are silently dropped — `__agent_help__()` owns the output, and the auto-doc + notes path never runs. A `UserWarning` is emitted, but warnings are easy to miss in agent shells, CI logs, and notebooks — **treat "both defined" as a hard review error** rather than something the warning will reliably catch. Fix it by folding the notes into `__agent_help__()`, or by dropping the custom `__agent_help__()` and letting the auto-doc + notes path run.
|
|
604
614
|
|
|
605
615
|
## Class docstring hints
|
|
606
616
|
|
|
@@ -632,10 +642,11 @@ If a class inherits from `AgentReadableMixin`, coding agents should call `agent_
|
|
|
632
642
|
|
|
633
643
|
### `agent_help(obj)`
|
|
634
644
|
|
|
635
|
-
Returns a string of agent-oriented documentation for a class, instance, or
|
|
645
|
+
Returns a string of agent-oriented documentation for a class, instance, module, function, or method.
|
|
636
646
|
|
|
637
|
-
- For classes and instances: if `__agent_help__()` is defined (via mixin or duck-typing), it is called and its return value is used verbatim — duck-typed implementations are responsible for their own formatting and notes are NOT auto-appended. Otherwise, auto-generated docs are produced from introspection, with `__agent_notes__()` from every class in the MRO appended automatically. If `__agent_help__()` raises, falls back to the auto-generated path (which does include notes).
|
|
638
|
-
- For modules: if the module defines a `__agent_help__` attribute (callable or string), it is used. Otherwise, auto-generated docs are produced from the module docstring and its public functions and classes.
|
|
647
|
+
- For classes and instances: if `__agent_help__()` is defined (via mixin or duck-typing), it is called and its return value is used verbatim — duck-typed implementations are responsible for their own formatting and notes are NOT auto-appended. If such a class also defines `__agent_notes__()`, a `UserWarning` is emitted because those notes are silently dropped (fold them into `__agent_help__()`, or drop the custom `__agent_help__()` to use the auto-doc path). Otherwise, auto-generated docs are produced from introspection, with `__agent_notes__()` from every class in the MRO appended automatically. If `__agent_help__()` raises, falls back to the auto-generated path (which does include notes).
|
|
648
|
+
- For modules: if the module defines a `__agent_help__` attribute (callable or string), it is used. Otherwise, auto-generated docs are produced from the module docstring and its public functions and classes. When the module defines `__all__`, that list is the authoritative public API (so re-exported symbols are included); otherwise public members are discovered by introspection, skipping private names and anything defined outside the module.
|
|
649
|
+
- For functions and methods (anything `inspect.isroutine` accepts): if the routine defines an `__agent_help__` attribute (callable or string), it is used. Otherwise, auto-generated docs render the signature, full docstring, and usage rules. A bound method's signature drops `self` and a classmethod's drops `cls`. If a callable `__agent_help__` raises, falls back to the auto-generated path.
|
|
639
650
|
|
|
640
651
|
## License
|
|
641
652
|
|