agent-readable 0.2.0__tar.gz → 0.2.1__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.
Files changed (30) hide show
  1. agent_readable-0.2.0/.github/workflows/test.yml → agent_readable-0.2.1/.github/workflows/ci.yml +7 -5
  2. {agent_readable-0.2.0 → agent_readable-0.2.1}/.github/workflows/publish.yml +5 -5
  3. {agent_readable-0.2.0 → agent_readable-0.2.1}/CHANGELOG.md +21 -1
  4. agent_readable-0.2.1/PKG-INFO +96 -0
  5. agent_readable-0.2.1/README.md +69 -0
  6. agent_readable-0.2.1/docs/authoring.md +79 -0
  7. agent_readable-0.2.1/docs/examples.md +253 -0
  8. agent_readable-0.2.1/docs/faq.md +50 -0
  9. agent_readable-0.2.1/docs/getting-started.md +148 -0
  10. agent_readable-0.2.1/docs/why.md +49 -0
  11. {agent_readable-0.2.0 → agent_readable-0.2.1}/pyproject.toml +1 -1
  12. agent_readable-0.2.0/PKG-INFO +0 -653
  13. agent_readable-0.2.0/README.md +0 -626
  14. {agent_readable-0.2.0 → agent_readable-0.2.1}/.gitignore +0 -0
  15. {agent_readable-0.2.0 → agent_readable-0.2.1}/LICENSE +0 -0
  16. {agent_readable-0.2.0 → agent_readable-0.2.1}/docs/agent_help_vs_help.gif +0 -0
  17. {agent_readable-0.2.0 → agent_readable-0.2.1}/examples/any_class.py +0 -0
  18. {agent_readable-0.2.0 → agent_readable-0.2.1}/examples/duck_type.py +0 -0
  19. {agent_readable-0.2.0 → agent_readable-0.2.1}/examples/modules_and_functions.py +0 -0
  20. {agent_readable-0.2.0 → agent_readable-0.2.1}/examples/sqlite_connection.py +0 -0
  21. {agent_readable-0.2.0 → agent_readable-0.2.1}/examples/temperature.py +0 -0
  22. {agent_readable-0.2.0 → agent_readable-0.2.1}/src/agent_readable/__init__.py +0 -0
  23. {agent_readable-0.2.0 → agent_readable-0.2.1}/src/agent_readable/__main__.py +0 -0
  24. {agent_readable-0.2.0 → agent_readable-0.2.1}/src/agent_readable/_model.py +0 -0
  25. {agent_readable-0.2.0 → agent_readable-0.2.1}/src/agent_readable/_protocol.py +0 -0
  26. {agent_readable-0.2.0 → agent_readable-0.2.1}/src/agent_readable/_render.py +0 -0
  27. {agent_readable-0.2.0 → agent_readable-0.2.1}/src/agent_readable/py.typed +0 -0
  28. {agent_readable-0.2.0 → agent_readable-0.2.1}/tests/__init__.py +0 -0
  29. {agent_readable-0.2.0 → agent_readable-0.2.1}/tests/test_cli.py +0 -0
  30. {agent_readable-0.2.0 → agent_readable-0.2.1}/tests/test_protocol.py +0 -0
@@ -1,4 +1,4 @@
1
- name: Tests
1
+ name: CI
2
2
 
3
3
  on:
4
4
  push:
@@ -10,10 +10,10 @@ jobs:
10
10
  lint:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
- - uses: actions/checkout@v4
13
+ - uses: actions/checkout@v6
14
14
 
15
15
  - name: Install uv
16
- uses: astral-sh/setup-uv@v3
16
+ uses: astral-sh/setup-uv@v8.2.0
17
17
 
18
18
  - name: Install dev deps
19
19
  run: uv sync --group dev
@@ -32,10 +32,12 @@ jobs:
32
32
  python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
33
33
 
34
34
  steps:
35
- - uses: actions/checkout@v4
35
+ - uses: actions/checkout@v6
36
36
 
37
37
  - name: Install uv
38
- uses: astral-sh/setup-uv@v3
38
+ uses: astral-sh/setup-uv@v8.2.0
39
+ with:
40
+ cache-suffix: py${{ matrix.python-version }}
39
41
 
40
42
  - name: Set up Python ${{ matrix.python-version }}
41
43
  run: uv python install ${{ matrix.python-version }}
@@ -9,16 +9,16 @@ jobs:
9
9
  build:
10
10
  runs-on: ubuntu-latest
11
11
  steps:
12
- - uses: actions/checkout@v4
12
+ - uses: actions/checkout@v6
13
13
 
14
14
  - name: Install uv
15
- uses: astral-sh/setup-uv@v3
15
+ uses: astral-sh/setup-uv@v8.2.0
16
16
 
17
17
  - name: Build sdist + wheel
18
18
  run: uv build
19
19
 
20
20
  - name: Upload artifacts
21
- uses: actions/upload-artifact@v4
21
+ uses: actions/upload-artifact@v7
22
22
  with:
23
23
  name: dist
24
24
  path: dist/
@@ -33,7 +33,7 @@ jobs:
33
33
  id-token: write
34
34
  steps:
35
35
  - name: Download artifacts
36
- uses: actions/download-artifact@v4
36
+ uses: actions/download-artifact@v8
37
37
  with:
38
38
  name: dist
39
39
  path: dist/
@@ -48,7 +48,7 @@ jobs:
48
48
  contents: write
49
49
  steps:
50
50
  - name: Download artifacts
51
- uses: actions/download-artifact@v4
51
+ uses: actions/download-artifact@v8
52
52
  with:
53
53
  name: dist
54
54
  path: dist/
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.1] - 2026-07-04
11
+
12
+ ### Documentation
13
+
14
+ - Restructured the README into a concise overview and moved detailed guidance
15
+ into focused docs for getting started, examples, authoring, rationale, and
16
+ FAQ.
17
+ - Added CI and PyPI badges to the README.
18
+ - Added `uv add`, `uvx`, `uv tool run`, and `pipx run` installation and
19
+ one-off execution examples.
20
+ - Added the TypeScript implementation under "Other Languages".
21
+
22
+ ### Changed
23
+
24
+ - Renamed the GitHub Actions test workflow file to `ci.yml` and its display
25
+ name to `CI`.
26
+ - Updated GitHub Actions versions to Node 24-compatible releases.
27
+ - Made the uv cache key unique for each Python version in the CI matrix.
28
+
10
29
  ## [0.1.2] - 2026-05-30
11
30
 
12
31
  ### Added
@@ -67,7 +86,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
67
86
  `AgentReadableMixin`, `__agent_notes__` accumulation across the MRO, module
68
87
  support, and the `python -m agent_readable` CLI.
69
88
 
70
- [Unreleased]: https://github.com/zydo/agent-readable/compare/v0.1.2...HEAD
89
+ [Unreleased]: https://github.com/zydo/agent-readable/compare/v0.2.1...HEAD
90
+ [0.2.1]: https://github.com/zydo/agent-readable/compare/v0.2.0...v0.2.1
71
91
  [0.1.2]: https://github.com/zydo/agent-readable/compare/v0.1.1...v0.1.2
72
92
  [0.1.1]: https://github.com/zydo/agent-readable/compare/v0.1.0...v0.1.1
73
93
  [0.1.0]: https://github.com/zydo/agent-readable/releases/tag/v0.1.0
@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-readable
3
+ Version: 0.2.1
4
+ Summary: A lightweight Python protocol for agent-oriented documentation
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
8
+ Author: zydo and agent-readable contributors
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent,agent-help,ai,ai-agent,coding-agent,context-engineering,docstring,documentation,llm,mixin,prompt-engineering,protocol,vibe-coding
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Software Development :: Code Generators
22
+ Classifier: Topic :: Software Development :: Documentation
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+
28
+ # agent-readable
29
+
30
+ [![CI](https://github.com/zydo/agent-readable/actions/workflows/ci.yml/badge.svg)](https://github.com/zydo/agent-readable/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/agent-readable.svg)](https://pypi.org/project/agent-readable/)
31
+
32
+ Stop coding agents from hallucinating Python APIs. `agent_help(target)` reads the live public API surface from any Python class, module, function, or method and renders compact, agent-oriented Markdown with current signatures and docstring summaries. When a library opts in, it can also return class-level usage rules such as lifecycle order, preconditions, and anti-patterns.
33
+
34
+ To let your coding agent automatically call `agent_help()` before using an unfamiliar API, install the companion skill:
35
+
36
+ ```bash
37
+ npx skills add zydo/skills --skill agent-readable
38
+ ```
39
+
40
+ <!-- markdownlint-disable MD033 -->
41
+ <p align="center">
42
+ <strong><code>logging.Logger</code> compared with <code>agent_help()</code> and <code>help()</code></strong><br>
43
+ <img src="docs/agent_help_vs_help.gif" alt="agent_help vs help">
44
+ </p>
45
+ <!-- markdownlint-enable MD033 -->
46
+
47
+ ## Quickstart
48
+
49
+ See [Getting started](docs/getting-started.md) for installation, one-off CLI usage with `uvx`, `uv tool run`, or `pipx`, and full CLI examples.
50
+
51
+ ```python
52
+ from agent_readable import agent_help
53
+ import logging
54
+
55
+ print(agent_help(logging.Logger))
56
+ ```
57
+
58
+ `agent_help()` works on plain Python objects with no setup required. It returns a curated public API list from runtime introspection, so agents see what exists in the installed version instead of guessing from stale training data.
59
+
60
+ Library authors can optionally add usage rules next to the code:
61
+
62
+ ```python
63
+ class Sensor:
64
+ """Reads a value from a hardware sensor."""
65
+
66
+ def read(self) -> float:
67
+ """Read the current sensor value."""
68
+
69
+ @classmethod
70
+ def __agent_notes__(cls) -> str:
71
+ return """
72
+ ## Do
73
+
74
+ - Call `calibrate()` once during setup, before `read()`.
75
+
76
+ ## Do not
77
+
78
+ - Do not call `read()` before calibration on first use.
79
+ """
80
+ ```
81
+
82
+ ## Docs
83
+
84
+ - [Getting started](docs/getting-started.md): installation, quickstart, CLI usage, and other language implementations.
85
+ - [Why it matters](docs/why.md): the API hallucination problem, token efficiency, and how this compares to other agent-doc patterns.
86
+ - [Examples](docs/examples.md): wrapping existing classes, inherited notes, duck typing, plain classes, modules, functions, and methods.
87
+ - [Authoring guide](docs/authoring.md): `__agent_help__`, `__agent_notes__`, class docstring hints, freshness guidance, and API reference.
88
+ - [FAQ](docs/faq.md): common questions about agent skills, docstrings, `AGENTS.md`, third-party libraries, and constrained decoding.
89
+
90
+ ## Other Languages
91
+
92
+ - TypeScript: [`agent-readable-ts`](https://github.com/zydo/agent-readable-ts)
93
+
94
+ ## License
95
+
96
+ [MIT](LICENSE)
@@ -0,0 +1,69 @@
1
+ # agent-readable
2
+
3
+ [![CI](https://github.com/zydo/agent-readable/actions/workflows/ci.yml/badge.svg)](https://github.com/zydo/agent-readable/actions/workflows/ci.yml) [![PyPI](https://img.shields.io/pypi/v/agent-readable.svg)](https://pypi.org/project/agent-readable/)
4
+
5
+ Stop coding agents from hallucinating Python APIs. `agent_help(target)` reads the live public API surface from any Python class, module, function, or method and renders compact, agent-oriented Markdown with current signatures and docstring summaries. When a library opts in, it can also return class-level usage rules such as lifecycle order, preconditions, and anti-patterns.
6
+
7
+ To let your coding agent automatically call `agent_help()` before using an unfamiliar API, install the companion skill:
8
+
9
+ ```bash
10
+ npx skills add zydo/skills --skill agent-readable
11
+ ```
12
+
13
+ <!-- markdownlint-disable MD033 -->
14
+ <p align="center">
15
+ <strong><code>logging.Logger</code> compared with <code>agent_help()</code> and <code>help()</code></strong><br>
16
+ <img src="docs/agent_help_vs_help.gif" alt="agent_help vs help">
17
+ </p>
18
+ <!-- markdownlint-enable MD033 -->
19
+
20
+ ## Quickstart
21
+
22
+ See [Getting started](docs/getting-started.md) for installation, one-off CLI usage with `uvx`, `uv tool run`, or `pipx`, and full CLI examples.
23
+
24
+ ```python
25
+ from agent_readable import agent_help
26
+ import logging
27
+
28
+ print(agent_help(logging.Logger))
29
+ ```
30
+
31
+ `agent_help()` works on plain Python objects with no setup required. It returns a curated public API list from runtime introspection, so agents see what exists in the installed version instead of guessing from stale training data.
32
+
33
+ Library authors can optionally add usage rules next to the code:
34
+
35
+ ```python
36
+ class Sensor:
37
+ """Reads a value from a hardware sensor."""
38
+
39
+ def read(self) -> float:
40
+ """Read the current sensor value."""
41
+
42
+ @classmethod
43
+ def __agent_notes__(cls) -> str:
44
+ return """
45
+ ## Do
46
+
47
+ - Call `calibrate()` once during setup, before `read()`.
48
+
49
+ ## Do not
50
+
51
+ - Do not call `read()` before calibration on first use.
52
+ """
53
+ ```
54
+
55
+ ## Docs
56
+
57
+ - [Getting started](docs/getting-started.md): installation, quickstart, CLI usage, and other language implementations.
58
+ - [Why it matters](docs/why.md): the API hallucination problem, token efficiency, and how this compares to other agent-doc patterns.
59
+ - [Examples](docs/examples.md): wrapping existing classes, inherited notes, duck typing, plain classes, modules, functions, and methods.
60
+ - [Authoring guide](docs/authoring.md): `__agent_help__`, `__agent_notes__`, class docstring hints, freshness guidance, and API reference.
61
+ - [FAQ](docs/faq.md): common questions about agent skills, docstrings, `AGENTS.md`, third-party libraries, and constrained decoding.
62
+
63
+ ## Other Languages
64
+
65
+ - TypeScript: [`agent-readable-ts`](https://github.com/zydo/agent-readable-ts)
66
+
67
+ ## License
68
+
69
+ [MIT](LICENSE)
@@ -0,0 +1,79 @@
1
+ # Authoring guide
2
+
3
+ ## Keeping agent docs up to date
4
+
5
+ Agent docs can go stale when classes change: new methods, changed behavior, or removed APIs. Install the companion skill to teach your agent to run `agent_help()` before modifying a class, prefer docstrings over `__agent_notes__()` for API summaries, and verify that the output stays accurate after changes.
6
+
7
+ ```bash
8
+ npx skills add zydo/skills --skill agent-readable
9
+ ```
10
+
11
+ ## The `__agent_help__` protocol
12
+
13
+ `__agent_help__()` is a dunder protocol for tool-specific documentation, similar in spirit to:
14
+
15
+ - `__doc__`: read by Python `help()`, Sphinx, IDEs, and REPLs.
16
+ - `__rich_repr__`: read by Rich when it renders an object.
17
+ - `__html__`: read by Django, Jinja2, and MarkupSafe when rendering HTML.
18
+
19
+ Unlike `__str__` or `__fspath__`, these dunders do not change Python runtime behavior. They are metadata slots a specific tool reads when it wants a representation. `__agent_help__` follows the same pattern for agent documentation.
20
+
21
+ Classes that define a `@classmethod` named `__agent_help__` returning a `str` are considered agent-readable. Modules can define a top-level `__agent_help__` attribute, either callable or string. Call the top-level `agent_help(obj)` function to get the docs, just like `str()` calls `__str__()`.
22
+
23
+ The `AgentReadable` `typing.Protocol` and `AgentReadableMixin` are provided for convenience and type-checking, but neither is required.
24
+
25
+ ## `__agent_help__` vs `__agent_notes__`
26
+
27
+ The two dunders intentionally encode different composition rules:
28
+
29
+ | Aspect | `__agent_help__()` | `__agent_notes__()` |
30
+ | --------------- | ------------------------------------------ | ----------------------------------------------------------------------------- |
31
+ | Semantics | Replacement: returned string is the output | Additive: appended to auto-generated docs |
32
+ | Composition | Single class wins, closest in MRO | Accumulated across the MRO; leaf class wins on conflict |
33
+ | When to use | Total control over rendered text | Auto-doc plus extra do/don't rules |
34
+ | Skipped when | Always called if defined | Silently dropped, with `UserWarning`, when custom `__agent_help__` is present |
35
+ | Mixin required? | No | No |
36
+
37
+ When a class defines both `__agent_help__()` and `__agent_notes__()`, the notes are silently dropped because `__agent_help__()` owns the output and the auto-doc plus 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 review error. Fix it by folding the notes into `__agent_help__()`, or by dropping custom `__agent_help__()` and letting the auto-doc plus notes path run.
38
+
39
+ ## Class docstring hints
40
+
41
+ For classes that inherit `AgentReadableMixin`, add a short hint in the class docstring:
42
+
43
+ ```python
44
+ class ResourcePool(AgentReadableMixin):
45
+ """
46
+ Rotates interchangeable resources such as API keys.
47
+
48
+ Agent usage:
49
+ Run ``agent_help(ResourcePool)`` before using this class in generated code.
50
+ """
51
+ ```
52
+
53
+ This way, even agents that only see the source or call `help()` are reminded to check `agent_help()`.
54
+
55
+ ## API reference
56
+
57
+ ### `agent_help(target)`
58
+
59
+ Render agent-oriented Markdown for a class, module, function, or method.
60
+
61
+ For classes, the output includes purpose, constructor, public API, default usage rules, and accumulated `__agent_notes__()` sections when present. For modules, it includes purpose, public functions, and public classes. For functions and methods, it includes signature, docstring, and default usage rules.
62
+
63
+ For classes and instances, if `__agent_help__()` is defined through the 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. If `__agent_help__()` raises, `agent_help()` falls back to the auto-generated path, which does include notes.
64
+
65
+ For modules, if the module defines a `__agent_help__` attribute, either 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.
66
+
67
+ For functions and methods, if the routine defines a `__agent_help__` attribute, either 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 signature drops `cls`. If a callable `__agent_help__` raises, `agent_help()` falls back to the auto-generated path.
68
+
69
+ ### `AgentReadable`
70
+
71
+ A runtime-checkable `typing.Protocol` that requires `__agent_help__() -> str`.
72
+
73
+ ### `AgentReadableMixin`
74
+
75
+ A mixin class for classes that provides a default `__agent_help__()` implementation using introspection. The mixin is convenience only: defining `__agent_notes__()` directly on any class also works, and notes are collected automatically regardless of inheritance from the mixin.
76
+
77
+ The mixin does not apply to modules; modules are supported directly by `agent_help()`.
78
+
79
+ If a class inherits from `AgentReadableMixin`, coding agents should call `agent_help(TheClass)` before generating code that uses it.
@@ -0,0 +1,253 @@
1
+ # Examples
2
+
3
+ These examples demonstrate five ways to use `agent_help()`: three with library-author opt-in and two on plain classes or modules with no setup.
4
+
5
+ ## Example 1: Wrapping an existing class
6
+
7
+ Add agent-readable docs to any class, including ones you do not own. Full example: [`examples/sqlite_connection.py`](../examples/sqlite_connection.py).
8
+
9
+ ```python
10
+ import sqlite3
11
+ from agent_readable import AgentReadableMixin, agent_help
12
+
13
+
14
+ class Connection(sqlite3.Connection, AgentReadableMixin):
15
+ """An agent-friendly wrapper around sqlite3.Connection."""
16
+
17
+ @classmethod
18
+ def __agent_notes__(cls) -> str:
19
+ return (
20
+ "Additional notes about using Connection here. "
21
+ "For example, common pitfalls, best practices, etc."
22
+ )
23
+ ```
24
+
25
+ Override `__agent_notes__()` to add extra guidance, or leave it out for auto-generated docs only.
26
+
27
+ `agent_help(Connection)` output excerpt:
28
+
29
+ ```text
30
+ # Connection
31
+
32
+ ## Purpose
33
+
34
+ An agent-friendly wrapper around sqlite3.Connection.
35
+
36
+ ## Public API
37
+
38
+ - `backup(target, *, pages=-1, progress=None, name='main', sleep=0.25)` method: Makes a backup of the database.
39
+ - `close()` method: Close the database connection.
40
+ - `commit()` method: Commit any pending transaction to the database.
41
+ - `execute(...)` method: Executes an SQL statement.
42
+ - `rollback()` method: Roll back to the start of any pending transaction.
43
+
44
+ ## Agent usage rules
45
+
46
+ - Prefer the public API listed above.
47
+ - Do not use private methods or attributes starting with `_`.
48
+ - Do not invent unsupported behavior.
49
+ - If usage is ambiguous, prefer the simplest documented usage pattern.
50
+
51
+ ## Notes from class Connection
52
+
53
+ Additional notes about using Connection here. For example, common pitfalls, best practices, etc.
54
+ ```
55
+
56
+ ## Example 2: Inheritance with accumulated notes
57
+
58
+ Override `__agent_notes__()` to add usage guidance. Notes accumulate through inheritance automatically. Full example: [`examples/temperature.py`](../examples/temperature.py).
59
+
60
+ ```python
61
+ from agent_readable import AgentReadableMixin, agent_help
62
+
63
+
64
+ class Sensor(AgentReadableMixin):
65
+ """Reads a value from a hardware sensor."""
66
+
67
+ def __init__(self, pin: int, *, unit: str = "C"): ...
68
+
69
+ def read(self) -> float:
70
+ """Read the current sensor value."""
71
+
72
+ def calibrate(self, offset: float):
73
+ """Apply a calibration offset."""
74
+
75
+ @classmethod
76
+ def __agent_notes__(cls) -> str:
77
+ return """
78
+ ## Do
79
+
80
+ - Call `calibrate()` once during setup, before `read()`.
81
+ - Handle negative values -- sensors may report below zero.
82
+
83
+ ## Do not
84
+
85
+ - Do not call `read()` before `calibrate()` on first use.
86
+ """
87
+
88
+
89
+ class CalibratedSensor(Sensor):
90
+ """A sensor with factory calibration applied."""
91
+
92
+ def reset(self):
93
+ """Reset to factory calibration."""
94
+
95
+ @classmethod
96
+ def __agent_notes__(cls) -> str:
97
+ return """
98
+ ## Do
99
+
100
+ - Call `reset()` if readings drift unexpectedly.
101
+
102
+ ## Do not
103
+
104
+ - Do not call `calibrate()` -- use `reset()` instead. Factory calibration
105
+ is pre-applied and `calibrate()` would double-adjust.
106
+ """
107
+ ```
108
+
109
+ `agent_help(CalibratedSensor)` includes notes from both classes. The child class's notes explicitly state they take precedence over the parent's, so the agent knows `reset()` replaces `calibrate()` for `CalibratedSensor`.
110
+
111
+ ## Example 3: Duck-typed custom output
112
+
113
+ Any class that defines a `__agent_help__()` classmethod works, with no inheritance required. Full example: [`examples/duck_type.py`](../examples/duck_type.py).
114
+
115
+ ```python
116
+ from agent_readable import agent_help
117
+
118
+
119
+ class RateLimiter:
120
+ """Token bucket rate limiter."""
121
+
122
+ def __init__(self, max_tokens: int, refill_rate: float): ...
123
+
124
+ def acquire(self, tokens: int = 1) -> bool:
125
+ """Try to acquire tokens. Returns False if rate-limited."""
126
+
127
+ def wait(self, tokens: int = 1) -> None:
128
+ """Block until tokens are available."""
129
+
130
+ @classmethod
131
+ def __agent_help__(cls) -> str:
132
+ return (
133
+ "# RateLimiter\n"
134
+ "\n"
135
+ "## Constructor\n"
136
+ "\n"
137
+ "```python\n"
138
+ "RateLimiter(max_tokens: int, refill_rate: float)\n"
139
+ "```\n"
140
+ "\n"
141
+ "## Do\n"
142
+ "\n"
143
+ "- Use `acquire()` for non-blocking checks.\n"
144
+ "- Use `wait()` when you must proceed regardless of rate.\n"
145
+ "- Set `refill_rate` to tokens/second.\n"
146
+ "\n"
147
+ "## Do not\n"
148
+ "\n"
149
+ "- Do not call `acquire()` in a tight loop without sleeping.\n"
150
+ "- Do not assume `acquire()` always returns True.\n"
151
+ )
152
+
153
+
154
+ print(agent_help(RateLimiter))
155
+ ```
156
+
157
+ Use `__agent_help__()` when you need total control over the rendered output. Use `__agent_notes__()` when you want auto-generated API docs plus your extra rules.
158
+
159
+ ## Example 4: Any class, no setup required
160
+
161
+ Even without the mixin or duck typing, `agent_help()` generates structured Markdown from introspection: a curated public API list with current signatures, free of inherited dunders and MRO clutter. Full example: [`examples/any_class.py`](../examples/any_class.py).
162
+
163
+ ```python
164
+ import logging
165
+ from agent_readable import agent_help
166
+
167
+ print(agent_help(logging.Logger))
168
+ ```
169
+
170
+ Output excerpt:
171
+
172
+ ````
173
+ # Logger
174
+
175
+ ## Constructor
176
+
177
+ ```python
178
+ Logger(name, level=0)
179
+ ```
180
+
181
+ ## Purpose
182
+
183
+ Instances of the Logger class represent a single logging channel. A
184
+ "logging channel" indicates an area of an application.
185
+
186
+ ## Public API
187
+
188
+ - `addFilter(filter)` method: Add the specified filter to this handler.
189
+ - `addHandler(hdlr)` method: Add the specified handler to this logger.
190
+ - `debug(msg, *args, **kwargs)` method: Log 'msg % args' with severity 'DEBUG'.
191
+ - `error(msg, *args, **kwargs)` method: Log 'msg % args' with severity 'ERROR'.
192
+ - `info(msg, *args, **kwargs)` method: Log 'msg % args' with severity 'INFO'.
193
+ - `setLevel(level)` method: Set the logging level of this logger.
194
+ - `warning(msg, *args, **kwargs)` method: Log 'msg % args' with severity 'WARNING'.
195
+ ````
196
+
197
+ No mixin, no duck typing: just pass any class to `agent_help()`.
198
+
199
+ ## Example 5: Modules, functions, and methods
200
+
201
+ `agent_help()` also works on modules, functions, and methods. Full example: [`examples/modules_and_functions.py`](../examples/modules_and_functions.py).
202
+
203
+ ```python
204
+ import sys
205
+ from agent_readable import agent_help
206
+
207
+ print(agent_help(sys.modules[__name__]))
208
+ ```
209
+
210
+ Module output includes the module docstring, public functions, and classes:
211
+
212
+ ````python
213
+ # __main__
214
+
215
+ ## Purpose
216
+
217
+ Example: Using agent_help() on modules, functions, and methods.
218
+
219
+ ## Public API
220
+
221
+ - `Query` class: Build and execute a query.
222
+ - `connect(host: str, port: int = 5432) -> str` function: Connect to a database server.
223
+ - `disconnect()` function: Close the connection.
224
+
225
+ ## Agent usage rules
226
+
227
+ - Prefer the public API listed above.
228
+ - Do not use private names starting with `_`.
229
+ - Do not invent unsupported behavior.
230
+ - If usage is ambiguous, prefer the simplest documented usage pattern.
231
+ ````
232
+
233
+ You can also pass any stdlib or third-party module:
234
+
235
+ ```python
236
+ import pathlib
237
+ from agent_readable import agent_help
238
+
239
+ print(agent_help(pathlib))
240
+ ```
241
+
242
+ If the module defines `__all__`, that list is honored as the authoritative public API, including symbols re-exported from other modules.
243
+
244
+ Functions and methods render their signature, full docstring, and usage rules:
245
+
246
+ ```python
247
+ import pathlib
248
+ from agent_readable import agent_help
249
+
250
+ print(agent_help(pathlib.Path.read_text))
251
+ ```
252
+
253
+ Modules support less customization than classes. You can override generated module output entirely by setting a module-level `__agent_help__` attribute, but this is discouraged because it replaces the auto-generated summary, signatures, purpose, and public API list. Prefer clear module, function, and class docstrings instead.
@@ -0,0 +1,50 @@
1
+ # FAQ
2
+
3
+ ## How does my agent know to call `agent_help()` instead of `help()`?
4
+
5
+ Install the companion agent skill:
6
+
7
+ ```bash
8
+ npx skills add zydo/skills --skill agent-readable
9
+ ```
10
+
11
+ 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.
12
+
13
+ Cursor is among the adopters too, but its skill integration is manual: invoke the skill explicitly there rather than relying on description-match auto-activation.
14
+
15
+ ## How is this different from `AGENTS.md`, `llms.txt`, or Cursor rules?
16
+
17
+ Different granularity, different drift profile.
18
+
19
+ `AGENTS.md`, `llms.txt`, and `.cursor/rules` are project-level: one file per repo. They are good for rules like "use pnpm," "run lint before commit," or "this codebase prefers functional style."
20
+
21
+ `agent-readable` is class- or module-level: rules live next to the API they describe. It is better for guidance like "`ResourcePool.call()` is for non-streaming requests; for streaming, use `stream()` instead."
22
+
23
+ Use both. They do not compete. The advantage of class-level docs is that they travel with the code. When someone refactors `ResourcePool` into two classes, the rules move with the relevant class in the same PR instead of sitting stale in a sidecar file.
24
+
25
+ ## Why not just write better docstrings?
26
+
27
+ Docstrings answer "what does this do?" They are not designed for "when may I call this?" or "what is the wrong way to use this?"
28
+
29
+ Mixing both categories into the docstring makes the API summary noisier without helping agents reliably find usage rules. `__agent_notes__()` is for the second category, and it accumulates across the MRO automatically. Class docstrings do not compose like that.
30
+
31
+ ## Does this work for libraries I do not own?
32
+
33
+ Yes. Two common options:
34
+
35
+ - Subclass the target class and add `AgentReadableMixin` or `__agent_notes__()`.
36
+ - Monkey-patch: `ThirdPartyClass.__agent_notes__ = classmethod(lambda cls: "...")`.
37
+
38
+ `agent_help()` collects notes from the entire MRO; the mixin is not required.
39
+
40
+ ## Does it work without my class doing anything?
41
+
42
+ Yes. `agent_help()` falls back to introspection. 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.
43
+
44
+ ## Is `agent_help()` the strongest fix for API hallucination?
45
+
46
+ No. The strongest known mitigation is constrained decoding at the harness or decoder layer: masking illegal API tokens before generation, so the model cannot produce a nonexistent method at all.
47
+
48
+ `agent_help()` takes a 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.
49
+
50
+ 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 decoder. Either way, verify generated code before merging.