lynx-agent 1.0.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.
Files changed (81) hide show
  1. lynx_agent-1.0.0/.gitignore +42 -0
  2. lynx_agent-1.0.0/CHANGELOG.md +92 -0
  3. lynx_agent-1.0.0/CODE_OF_CONDUCT.md +35 -0
  4. lynx_agent-1.0.0/CONTRIBUTING.md +89 -0
  5. lynx_agent-1.0.0/LICENSE +17 -0
  6. lynx_agent-1.0.0/Makefile +23 -0
  7. lynx_agent-1.0.0/PKG-INFO +343 -0
  8. lynx_agent-1.0.0/README.md +268 -0
  9. lynx_agent-1.0.0/SECURITY.md +51 -0
  10. lynx_agent-1.0.0/benchmarks/README.md +56 -0
  11. lynx_agent-1.0.0/benchmarks/bench_end_to_end.py +97 -0
  12. lynx_agent-1.0.0/benchmarks/bench_pdp.py +82 -0
  13. lynx_agent-1.0.0/docs/00-execution-plan.md +201 -0
  14. lynx_agent-1.0.0/docs/01-data-model.md +371 -0
  15. lynx_agent-1.0.0/docs/02-policy-language.md +318 -0
  16. lynx_agent-1.0.0/docs/03-sdk-and-cli.md +290 -0
  17. lynx_agent-1.0.0/docs/concepts.md +176 -0
  18. lynx_agent-1.0.0/docs/cookbook.md +294 -0
  19. lynx_agent-1.0.0/docs/faq.md +158 -0
  20. lynx_agent-1.0.0/docs/getting-started.md +147 -0
  21. lynx_agent-1.0.0/docs/threat-model.md +132 -0
  22. lynx_agent-1.0.0/docs/why-lynx.md +68 -0
  23. lynx_agent-1.0.0/examples/01_hello_allow.py +131 -0
  24. lynx_agent-1.0.0/examples/02_block_dangerous.py +164 -0
  25. lynx_agent-1.0.0/examples/03_preview_writes.py +197 -0
  26. lynx_agent-1.0.0/examples/04_human_approval.py +190 -0
  27. lynx_agent-1.0.0/examples/05_real_llm_blocked.py +197 -0
  28. lynx_agent-1.0.0/examples/06_compliance_audit.py +202 -0
  29. lynx_agent-1.0.0/examples/07_refund_workflow.py +176 -0
  30. lynx_agent-1.0.0/examples/08_sql_transform.py +150 -0
  31. lynx_agent-1.0.0/examples/09_fastapi_service.py +235 -0
  32. lynx_agent-1.0.0/examples/10_devops_assistant.py +263 -0
  33. lynx_agent-1.0.0/examples/11_flask_service.py +209 -0
  34. lynx_agent-1.0.0/examples/12_django_service.py +246 -0
  35. lynx_agent-1.0.0/examples/README.md +98 -0
  36. lynx_agent-1.0.0/examples/policies/devops.yaml +103 -0
  37. lynx_agent-1.0.0/examples/policies/refund.yaml +55 -0
  38. lynx_agent-1.0.0/examples/policies/sql-transform.yaml +37 -0
  39. lynx_agent-1.0.0/pyproject.toml +173 -0
  40. lynx_agent-1.0.0/src/lynx/__init__.py +60 -0
  41. lynx_agent-1.0.0/src/lynx/adapters/__init__.py +1 -0
  42. lynx_agent-1.0.0/src/lynx/adapters/anthropic_sdk.py +174 -0
  43. lynx_agent-1.0.0/src/lynx/adapters/crewai_adapter.py +71 -0
  44. lynx_agent-1.0.0/src/lynx/adapters/langgraph_adapter.py +80 -0
  45. lynx_agent-1.0.0/src/lynx/adapters/mcp.py +93 -0
  46. lynx_agent-1.0.0/src/lynx/adapters/openai_sdk.py +113 -0
  47. lynx_agent-1.0.0/src/lynx/cli/__init__.py +1 -0
  48. lynx_agent-1.0.0/src/lynx/cli/main.py +382 -0
  49. lynx_agent-1.0.0/src/lynx/core/__init__.py +1 -0
  50. lynx_agent-1.0.0/src/lynx/core/mediator.py +228 -0
  51. lynx_agent-1.0.0/src/lynx/core/policy.py +514 -0
  52. lynx_agent-1.0.0/src/lynx/core/scheduler.py +484 -0
  53. lynx_agent-1.0.0/src/lynx/core/types.py +327 -0
  54. lynx_agent-1.0.0/src/lynx/decorators.py +109 -0
  55. lynx_agent-1.0.0/src/lynx/observability.py +106 -0
  56. lynx_agent-1.0.0/src/lynx/policy.py +31 -0
  57. lynx_agent-1.0.0/src/lynx/py.typed +0 -0
  58. lynx_agent-1.0.0/src/lynx/runtime.py +184 -0
  59. lynx_agent-1.0.0/src/lynx/sandbox.py +130 -0
  60. lynx_agent-1.0.0/src/lynx/sdk.py +51 -0
  61. lynx_agent-1.0.0/src/lynx/shadows/__init__.py +33 -0
  62. lynx_agent-1.0.0/src/lynx/shadows/filesystem.py +35 -0
  63. lynx_agent-1.0.0/src/lynx/shadows/http.py +44 -0
  64. lynx_agent-1.0.0/src/lynx/shadows/shell.py +61 -0
  65. lynx_agent-1.0.0/src/lynx/shadows/sql.py +56 -0
  66. lynx_agent-1.0.0/src/lynx/stores/__init__.py +5 -0
  67. lynx_agent-1.0.0/src/lynx/stores/postgres.py +271 -0
  68. lynx_agent-1.0.0/src/lynx/stores/sqlite.py +467 -0
  69. lynx_agent-1.0.0/tests/__init__.py +0 -0
  70. lynx_agent-1.0.0/tests/test_adapters.py +159 -0
  71. lynx_agent-1.0.0/tests/test_audit_chain.py +71 -0
  72. lynx_agent-1.0.0/tests/test_cli.py +49 -0
  73. lynx_agent-1.0.0/tests/test_end_to_end.py +116 -0
  74. lynx_agent-1.0.0/tests/test_framework_adapters.py +69 -0
  75. lynx_agent-1.0.0/tests/test_mediator.py +146 -0
  76. lynx_agent-1.0.0/tests/test_policy.py +169 -0
  77. lynx_agent-1.0.0/tests/test_resume.py +114 -0
  78. lynx_agent-1.0.0/tests/test_sandbox.py +54 -0
  79. lynx_agent-1.0.0/tests/test_security.py +55 -0
  80. lynx_agent-1.0.0/tests/test_shadows.py +99 -0
  81. lynx_agent-1.0.0/tests/test_types.py +51 -0
@@ -0,0 +1,42 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ build/
5
+ dist/
6
+ .eggs/
7
+
8
+ .pytest_cache/
9
+ .mypy_cache/
10
+ .ruff_cache/
11
+ .coverage
12
+ htmlcov/
13
+
14
+ .venv/
15
+ venv/
16
+ env/
17
+
18
+ .lynx/
19
+ *.db
20
+ *.db-journal
21
+ *.db-wal
22
+ *.db-shm
23
+
24
+ .DS_Store
25
+ .idea/
26
+ .vscode/
27
+
28
+ # Locally generated by `lynx init` in the repo root — never commit.
29
+ /policy.yaml
30
+ /lynx.toml
31
+ /demo-workspace/
32
+ /data/
33
+
34
+ # Wheel/sdist build outputs
35
+ dist/
36
+ *.whl
37
+ *.tar.gz
38
+
39
+ # Internal working docs — research notes, planning, scratch.
40
+ # Never gets committed; see internal/README.md for what lives there.
41
+ /internal/
42
+
@@ -0,0 +1,92 @@
1
+ # Changelog
2
+
3
+ All notable changes to Lynx will be documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning follows [SemVer](https://semver.org/spec/v2.0.0.html).
4
+
5
+ ## [Unreleased]
6
+
7
+ ### Added
8
+ - (nothing yet — open a PR!)
9
+
10
+ ### Changed
11
+ - (nothing yet)
12
+
13
+ ### Fixed
14
+ - (nothing yet)
15
+
16
+ ## [1.0.0] — 2026-06-09
17
+
18
+ First public release. All of the below shipped together; this is the surface area covered by the v1.0 SemVer commitment.
19
+
20
+ ### Core
21
+
22
+ - Kernel types: `Task`, `Run`, `Step`, `ActionRequest`, `Decision`, `AuditEvent`, `ToolMetadata`, `ExecutionContext`, `Principal`, `Budget`, `ModelCall`, `ActionResult`.
23
+ - Policy compiler + Policy Decision Point (PDP) — pure, deterministic, content-addressed bundles.
24
+ - Action Mediator (PEP) — five verdicts: `allow`, `deny`, `dry_run`, `approve_required`, `transform`.
25
+ - Scheduler with pre-execution checkpointing; crash-resume + approval-resume both correctly implemented.
26
+ - Hash-chained audit log with tamper detection (`lynx audit verify`).
27
+
28
+ ### Public SDK
29
+
30
+ - `@tool` decorator + `.shadow` for dry-run twins.
31
+ - `Runtime.run / resume / replay / approve / deny`.
32
+ - `Agent` protocol — one method, `async def step(conversation) -> ToolCall | FinalAnswer`.
33
+
34
+ ### Adapters
35
+
36
+ - `lynx.adapters.anthropic_sdk.ClaudeAgent`
37
+ - `lynx.adapters.openai_sdk.OpenAIAgent`
38
+ - `lynx.adapters.langgraph_adapter.LangGraphAgent`
39
+ - `lynx.adapters.crewai_adapter.CrewAIAgent`
40
+ - `lynx.adapters.mcp.register_mcp_server`
41
+
42
+ ### Storage
43
+
44
+ - `lynx.stores.sqlite.SQLiteStore` — full implementation, default.
45
+ - `lynx.stores.postgres.PostgresStore` — production backend (Tasks / Runs / Audit; Steps + Approvals follow same translation pattern).
46
+
47
+ ### Shadow library
48
+
49
+ - `lynx.shadows.shell_shadow`
50
+ - `lynx.shadows.write_file_shadow`, `delete_file_shadow`
51
+ - `lynx.shadows.sql_shadow`
52
+ - `lynx.shadows.http_shadow` (with built-in `Authorization` header redaction)
53
+
54
+ ### Sandbox
55
+
56
+ - `lynx.sandbox.run_in_subprocess` — POSIX subprocess sandbox with `RLIMIT_CPU`, `RLIMIT_AS`, stripped env, timeout.
57
+
58
+ ### Observability
59
+
60
+ - `lynx.observability.enable_prometheus`
61
+ - `lynx.observability.enable_otel`
62
+
63
+ ### CLI
64
+
65
+ - `lynx init / run / resume / ps / trace / approvals / approve / deny / audit verify / audit export / policy lint / policy bundle-id`
66
+
67
+ ### Documentation
68
+
69
+ - Onboarding: `why-lynx.md`, `getting-started.md`, `concepts.md`, `cookbook.md`, `faq.md`.
70
+ - Reference: `01-data-model.md`, `02-policy-language.md`, `03-sdk-and-cli.md`.
71
+ - Threat model: `threat-model.md` (STRIDE-style).
72
+ - 12 runnable examples: simple → complex → advanced → complete → integrations (FastAPI / Flask / Django).
73
+
74
+ ### Quality bar
75
+
76
+ - 57 tests, ~1.2s suite, 9-job CI matrix (Linux / macOS / Windows × Python 3.11 / 3.12 / 3.13) + coverage.
77
+ - ruff lint + format clean. `mypy --strict` runs (currently soft-gated on the test matrix; will be hard-gated in v1.1).
78
+ - Apache-2.0 licensed. PEP 561 typed (`py.typed`). PEP 639 license metadata.
79
+
80
+ ### Public API surface guaranteed by SemVer
81
+
82
+ - `lynx.tool`, `lynx.runtime`, `lynx.Runtime`, `lynx.shadow`, `lynx.allow/deny/dry_run/approve_required/transform/rule`.
83
+ - `lynx.Agent`, `lynx.Message`, `lynx.ToolCall`, `lynx.FinalAnswer`, `lynx.AgentAction`.
84
+ - `lynx.Task`, `lynx.Run`, `lynx.Step`, `lynx.ActionRequest`, `lynx.Decision`, `lynx.AuditEvent`, `lynx.Verdict`, `lynx.RunStatus`, `lynx.Principal`, `lynx.Budget`, `lynx.ToolMetadata`, `lynx.ExecutionContext`, `lynx.ModelCall`, `lynx.ActionResult`.
85
+ - Adapters and stores have their own public-class interfaces guaranteed.
86
+ - The YAML policy v1 grammar.
87
+ - The CLI command surface and exit codes.
88
+
89
+ Internal modules (`lynx.core.*`) are NOT part of the public API and may change in any minor release.
90
+
91
+ [Unreleased]: https://github.com/hadihonarvar/lynx/compare/v1.0.0...HEAD
92
+ [1.0.0]: https://github.com/hadihonarvar/lynx/releases/tag/v1.0.0
@@ -0,0 +1,35 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in the Lynx community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
8
+
9
+ ## Our standards
10
+
11
+ Examples of behavior that contributes to a positive environment:
12
+
13
+ - Demonstrating empathy and kindness toward other people
14
+ - Being respectful of differing opinions, viewpoints, and experiences
15
+ - Giving and gracefully accepting constructive feedback
16
+ - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
17
+ - Focusing on what is best not just for us as individuals, but for the overall community
18
+
19
+ Examples of unacceptable behavior:
20
+
21
+ - The use of sexualized language or imagery, and sexual attention or advances of any kind
22
+ - Trolling, insulting or derogatory comments, and personal or political attacks
23
+ - Public or private harassment
24
+ - Publishing others' private information, such as a physical or email address, without their explicit permission
25
+ - Other conduct which could reasonably be considered inappropriate in a professional setting
26
+
27
+ ## Enforcement
28
+
29
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the project maintainers via [GitHub Security Advisories](https://github.com/hadihonarvar/lynx/security/advisories/new) (any "Conduct" report routes to maintainers privately). All complaints will be reviewed and investigated promptly and fairly.
30
+
31
+ All community leaders are obligated to respect the privacy and security of the reporter of any incident.
32
+
33
+ ## Attribution
34
+
35
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
@@ -0,0 +1,89 @@
1
+ # Contributing to Lynx
2
+
3
+ Thanks for considering a contribution. This document covers what to do and what to expect.
4
+
5
+ ## Quick setup
6
+
7
+ ```bash
8
+ git clone https://github.com/<your-fork>/lynx
9
+ cd lynx
10
+ python3 -m venv .venv
11
+ source .venv/bin/activate
12
+ pip install -e ".[dev]"
13
+ make all # fmt + lint + type + test — should be green
14
+ ```
15
+
16
+ ## Filing issues
17
+
18
+ Open an issue using one of the [templates](.github/ISSUE_TEMPLATE/) — `bug`, `feature`, or `question`. The more reproduction info you include, the faster we can act.
19
+
20
+ ## Proposing changes
21
+
22
+ 1. **Open an issue first** for non-trivial changes — saves you wasted effort if the design doesn't fit. Trivial fixes (typos, small bugs, clearer error messages) can skip straight to a PR.
23
+ 2. **Branch from `main`**, with a name like `fix/policy-regex-timeout` or `feat/postgres-store`.
24
+ 3. **One logical change per PR.** Smaller PRs land faster.
25
+ 4. **Tests required** for new behavior. Bug fixes should include a regression test.
26
+ 5. **Update docs** when you change the public API or CLI surface.
27
+ 6. **Run `make all` locally** before pushing. CI runs the same checks; saving a round-trip helps.
28
+
29
+ ## Architecture rules
30
+
31
+ These are load-bearing — please don't break them:
32
+
33
+ 1. **`core/` has zero I/O.** It's pure functions and state machines. If you need to do I/O, it goes in `stores/`, `adapters/`, `transports/`, or `cli/`.
34
+ 2. **The PDP is deterministic.** No network, no clocks read inside policy evaluation, no random. Same input must always produce the same `Decision`.
35
+ 3. **The audit chain is append-only.** If you find yourself wanting to mutate a past `AuditEvent`, you're solving the wrong problem.
36
+ 4. **Tools must be async.** A sync tool is `asyncio.to_thread(...)` away from being async; please wrap rather than introducing sync paths into the kernel.
37
+ 5. **No breaking changes to the public API in patch releases.** We follow SemVer strictly from v1.0 onwards.
38
+
39
+ ## Adding a new adapter
40
+
41
+ The smallest viable PR for a new framework adapter:
42
+
43
+ 1. `src/lynx/adapters/<framework>.py` — a class that satisfies the `Agent` protocol (`async def step(conversation) -> ToolCall | FinalAnswer`).
44
+ 2. `tests/test_adapter_<framework>.py` — mock the framework's client; assert the message translation + tool-call extraction.
45
+ 3. `examples/<framework>_demo.py` — a runnable demo using the new adapter.
46
+ 4. Update the README's adapter list.
47
+
48
+ ## Adding a new shadow
49
+
50
+ `src/lynx/shadows/<name>.py` — one or more `async def name_shadow(*args) -> dict` functions that return previews without side effects.
51
+
52
+ ## Coding style
53
+
54
+ - Python 3.11+
55
+ - `ruff` for lint + format
56
+ - `mypy --strict` for types
57
+ - One blank line between methods, two between top-level definitions
58
+ - Docstrings on every public function — short and useful, not ceremonial
59
+
60
+ ## Commit messages
61
+
62
+ Conventional Commits style:
63
+
64
+ - `fix: policy regex denial-of-service guard`
65
+ - `feat(stores): postgres backend`
66
+ - `docs: clarify approve flow`
67
+ - `test: cover budget exhaustion`
68
+ - `chore: bump ruff to 0.6`
69
+
70
+ ## Release process
71
+
72
+ Maintainers only:
73
+
74
+ 1. Update `CHANGELOG.md`
75
+ 2. Bump version in `pyproject.toml` and `src/lynx/__init__.py`
76
+ 3. `git tag vX.Y.Z` + push tag
77
+ 4. GitHub Actions handles wheel build + PyPI publish via OIDC trusted publishing
78
+
79
+ ## Code of conduct
80
+
81
+ By participating you agree to follow the [Contributor Covenant](CODE_OF_CONDUCT.md). In short: be kind, be patient, assume good intent, and call out behavior that crosses lines.
82
+
83
+ ## Security issues
84
+
85
+ Do **not** open public issues for security vulnerabilities. Follow the process in [SECURITY.md](SECURITY.md).
86
+
87
+ ## Licensing
88
+
89
+ By contributing, you agree your contributions will be licensed under the Apache License 2.0.
@@ -0,0 +1,17 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Copyright 2026 Lynx contributors
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
@@ -0,0 +1,23 @@
1
+ .PHONY: install test lint type fmt all clean
2
+
3
+ install:
4
+ pip install -e ".[dev]"
5
+
6
+ test:
7
+ pytest -v
8
+
9
+ lint:
10
+ ruff check src tests
11
+
12
+ fmt:
13
+ ruff format src tests
14
+ ruff check --fix src tests
15
+
16
+ type:
17
+ mypy src
18
+
19
+ all: fmt lint type test
20
+
21
+ clean:
22
+ rm -rf build dist *.egg-info .pytest_cache .mypy_cache .ruff_cache
23
+ find . -type d -name __pycache__ -exec rm -rf {} +
@@ -0,0 +1,343 @@
1
+ Metadata-Version: 2.4
2
+ Name: lynx-agent
3
+ Version: 1.0.0
4
+ Summary: Framework-agnostic runtime that makes any AI agent safe and reliable enough to put in production: policy-gated execution, durable checkpointing, hash-chained audit.
5
+ Project-URL: Homepage, https://github.com/hadihonarvar/lynx
6
+ Project-URL: Repository, https://github.com/hadihonarvar/lynx
7
+ Project-URL: Documentation, https://github.com/hadihonarvar/lynx/tree/main/docs
8
+ Project-URL: Issues, https://github.com/hadihonarvar/lynx/issues
9
+ Project-URL: Changelog, https://github.com/hadihonarvar/lynx/blob/main/CHANGELOG.md
10
+ Author: Lynx contributors
11
+ License-Expression: Apache-2.0
12
+ License-File: LICENSE
13
+ Keywords: agentic,agents,ai,audit,claude,crewai,durable-execution,langgraph,llm,mcp,openai,policy,reliability
14
+ Classifier: Development Status :: 5 - Production/Stable
15
+ Classifier: Framework :: AsyncIO
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Intended Audience :: Information Technology
18
+ Classifier: Intended Audience :: System Administrators
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Programming Language :: Python
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: Implementation :: CPython
26
+ Classifier: Topic :: Security
27
+ Classifier: Topic :: Software Development :: Libraries
28
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
29
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
30
+ Classifier: Topic :: System :: Monitoring
31
+ Classifier: Typing :: Typed
32
+ Requires-Python: >=3.11
33
+ Requires-Dist: click>=8.1
34
+ Requires-Dist: msgpack>=1.0
35
+ Requires-Dist: python-ulid>=2.2
36
+ Requires-Dist: pyyaml>=6.0
37
+ Requires-Dist: rich>=13.7
38
+ Requires-Dist: typing-extensions>=4.5
39
+ Provides-Extra: all
40
+ Requires-Dist: anthropic>=0.30; extra == 'all'
41
+ Requires-Dist: crewai>=0.40; extra == 'all'
42
+ Requires-Dist: langgraph>=0.2; extra == 'all'
43
+ Requires-Dist: mcp>=1.0; extra == 'all'
44
+ Requires-Dist: openai>=1.40; extra == 'all'
45
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.27; extra == 'all'
46
+ Requires-Dist: opentelemetry-sdk>=1.27; extra == 'all'
47
+ Requires-Dist: prometheus-client>=0.20; extra == 'all'
48
+ Requires-Dist: psycopg[binary]>=3.1; extra == 'all'
49
+ Provides-Extra: anthropic
50
+ Requires-Dist: anthropic>=0.30; extra == 'anthropic'
51
+ Provides-Extra: crewai
52
+ Requires-Dist: crewai>=0.40; extra == 'crewai'
53
+ Provides-Extra: dev
54
+ Requires-Dist: build>=1.2; extra == 'dev'
55
+ Requires-Dist: hypothesis>=6.100; extra == 'dev'
56
+ Requires-Dist: mypy>=1.10; extra == 'dev'
57
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
58
+ Requires-Dist: pytest>=8.0; extra == 'dev'
59
+ Requires-Dist: ruff>=0.5; extra == 'dev'
60
+ Requires-Dist: twine>=5.0; extra == 'dev'
61
+ Provides-Extra: langgraph
62
+ Requires-Dist: langgraph>=0.2; extra == 'langgraph'
63
+ Provides-Extra: mcp
64
+ Requires-Dist: mcp>=1.0; extra == 'mcp'
65
+ Provides-Extra: openai
66
+ Requires-Dist: openai>=1.40; extra == 'openai'
67
+ Provides-Extra: otel
68
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.27; extra == 'otel'
69
+ Requires-Dist: opentelemetry-sdk>=1.27; extra == 'otel'
70
+ Provides-Extra: postgres
71
+ Requires-Dist: psycopg[binary]>=3.1; extra == 'postgres'
72
+ Provides-Extra: prometheus
73
+ Requires-Dist: prometheus-client>=0.20; extra == 'prometheus'
74
+ Description-Content-Type: text/markdown
75
+
76
+ # Lynx
77
+
78
+ **Make any AI agent safe and reliable enough to put in production.** Open-source Python runtime that wraps any agent (LangGraph, CrewAI, OpenAI Agents SDK, Anthropic Agent SDK, or a plain Python loop) and gives you three things every team currently rebuilds from scratch:
79
+
80
+ 1. **Policy-gated execution** — every tool call passes through a declarative YAML policy engine. Dry-run, deny, transform, or require human approval.
81
+ 2. **Durable execution** — every step is checkpointed before its side effect. Crash mid-run, resume exactly where you left off, no double-execution.
82
+ 3. **Hash-chained audit log** — content-addressed, tamper-evident, regulator-grade trail of every decision and action.
83
+
84
+ > Think *Envoy + Temporal + OPA, but for AI agents.*
85
+
86
+ ---
87
+
88
+ ## Why
89
+
90
+ Agent reliability is the #1 unmet need in 2026 (Gartner: 40% of agentic AI projects will fail). Capabilities are up, reliability is lagging. Real incidents from the last 12 months:
91
+
92
+ - An AI agent **deleted a developer's entire `D:` drive** when asked to clear a cache folder.
93
+ - An AI agent **wiped a production AWS environment**, causing a 13-hour outage.
94
+ - Meta's AI safety director was unable to stop her own agent from **deleting her inbox**.
95
+ - An n8n v2.4.7→v2.6.3 upgrade silently **broke function-calling schemas** across the user base.
96
+
97
+ Every team building agents reinvents the same scaffolding: retry logic, dry-runs, approval flows, audit trails. **Lynx is the missing layer.**
98
+
99
+ ---
100
+
101
+ ## Quickstart (under 2 minutes)
102
+
103
+ ```bash
104
+ pip install lynx-agent
105
+ lynx init
106
+ ```
107
+
108
+ ```python
109
+ # my_agent.py
110
+ import asyncio
111
+ from lynx import tool, runtime, ToolCall, FinalAnswer, Message
112
+
113
+ @tool(cost="low", reversible=False, scope=["filesystem:write"])
114
+ async def shell(cmd: str) -> str:
115
+ proc = await asyncio.create_subprocess_shell(
116
+ cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
117
+ )
118
+ out, err = await proc.communicate()
119
+ return (out + err).decode()
120
+
121
+ @shell.shadow
122
+ async def _shell_shadow(cmd: str) -> dict:
123
+ return {"would_run": cmd}
124
+
125
+ class MyAgent:
126
+ """Replace with any LLM-backed agent."""
127
+ async def step(self, conversation):
128
+ # Pretend the LLM proposed a dangerous command
129
+ return ToolCall(tool="shell", args={"cmd": "rm -rf /"}, call_id="c1")
130
+
131
+ async def main():
132
+ result = await runtime.run(
133
+ MyAgent(),
134
+ task="clean up the workspace",
135
+ policy="./policy.yaml",
136
+ )
137
+ print(result.status, result.final_answer)
138
+
139
+ asyncio.run(main())
140
+ ```
141
+
142
+ ```bash
143
+ $ python my_agent.py
144
+ $ lynx ps # list runs
145
+ $ lynx trace <run_id> # see every step + policy decision
146
+ $ lynx audit verify <run_id> # verify the hash chain
147
+ ```
148
+
149
+ The default policy will **deny** the `rm -rf /` and feed the denial back to the agent as a tool result, so the agent can retry with something safer.
150
+
151
+ ---
152
+
153
+ ## How it works
154
+
155
+ ```
156
+ ┌────────────────────────────────────────────────┐
157
+ │ Agent (LangGraph / CrewAI / SDK / any) │
158
+ └──────────────────┬─────────────────────────────┘
159
+ │ proposed tool call
160
+
161
+ ╔════════════════════════════════════════════════╗
162
+ ║ AGENT RUNTIME ║
163
+ ║ ┌────────────┐ ┌────────────┐ ┌──────────┐ ║
164
+ ║ │ Scheduler │→ │ Policy PDP │→ │ Mediator │ ║
165
+ ║ │ (durable) │ │ (pure) │ │ (PEP) │ ║
166
+ ║ └────────────┘ └────────────┘ └──────────┘ ║
167
+ ║ ↓ ↓ ↓ ║
168
+ ║ ┌──────────────────────────────────────────┐ ║
169
+ ║ │ SQLite journal + audit chain │ ║
170
+ ║ └──────────────────────────────────────────┘ ║
171
+ ╚════════════════════════════════════════════════╝
172
+ │ approved + recorded
173
+
174
+ ┌────────────────────────────────────────────────┐
175
+ │ Real world (shell, browser, DB, AWS, etc.) │
176
+ └────────────────────────────────────────────────┘
177
+ ```
178
+
179
+ Every action passes through the **Mediator**. The PDP returns one of five verdicts (`allow`, `deny`, `dry_run`, `approve_required`, `transform`). The Mediator dispatches accordingly. Before any side effect, a checkpoint is written. Every step emits a hash-chained audit event.
180
+
181
+ ---
182
+
183
+ ## Policy example
184
+
185
+ ```yaml
186
+ # policy.yaml
187
+ version: 1
188
+ defaults:
189
+ on_missing_shadow: approve_required
190
+ on_no_match: deny
191
+
192
+ rules:
193
+ - id: read-only-allow
194
+ match: { declared.scope.contains_any: ["filesystem:read", "net:read"] }
195
+ decision: allow
196
+
197
+ - id: shell-rm-rf-root
198
+ match:
199
+ tool: shell
200
+ args.cmd.matches: '^\s*rm\s+(-[rRf]+\s+)+/(\s|$)'
201
+ decision: deny
202
+ reason: "rm -rf / is never allowed"
203
+
204
+ - id: prod-mutations-need-approval
205
+ match:
206
+ context.environment: prod
207
+ declared.scope.contains_any: ["filesystem:write", "db:write", "cloud:write"]
208
+ decision: approve_required
209
+ approvers: ["@oncall"]
210
+
211
+ - id: irreversible-dry-run-first
212
+ match: { declared.reversible: false }
213
+ decision: dry_run
214
+ ```
215
+
216
+ Three layers, increasing expressiveness:
217
+ 1. **YAML rules** — 80% of cases
218
+ 2. **Predicates** — reusable named patterns
219
+ 3. **Python escape hatch** — `@policy.rule` for edge cases
220
+
221
+ See `docs/02-policy-language.md` for the full grammar.
222
+
223
+ ---
224
+
225
+ ## CLI
226
+
227
+ ```
228
+ lynx init # set up a project
229
+ lynx run <script> # run an agent script
230
+ lynx ps # list recent runs
231
+ lynx trace <run-id> # step-by-step trace
232
+ lynx approvals # list pending approvals
233
+ lynx approve <approval-id> # approve a pending request
234
+ lynx audit verify <run-id> # verify the hash chain
235
+ lynx audit export <run-id> # emit jsonl for compliance
236
+ lynx policy lint # validate policy.yaml
237
+ lynx policy bundle-id # content-addressed bundle ID
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Repo layout
243
+
244
+ ```
245
+ lynx/
246
+ ├── docs/
247
+ │ ├── 00-execution-plan.md ← read first
248
+ │ ├── 01-data-model.md
249
+ │ ├── 02-policy-language.md
250
+ │ └── 03-sdk-and-cli.md
251
+ ├── src/lynx/
252
+ │ ├── core/ ← pure kernel, no I/O
253
+ │ │ ├── types.py
254
+ │ │ ├── policy.py ← PDP
255
+ │ │ ├── mediator.py ← PEP
256
+ │ │ └── scheduler.py ← step loop
257
+ │ ├── stores/ ← pluggable I/O
258
+ │ │ └── sqlite.py
259
+ │ ├── cli/main.py
260
+ │ ├── decorators.py ← @tool, @shadow
261
+ │ ├── policy.py ← top-level re-exports
262
+ │ ├── runtime.py ← public Runtime facade
263
+ │ └── sdk.py ← Agent protocol + Message types
264
+ ├── tests/
265
+ ├── examples/
266
+ │ └── hello_agent.py
267
+ └── pyproject.toml
268
+ ```
269
+
270
+ **Architectural rule:** `core/` has zero I/O. All I/O lives in `stores/`, `adapters/`, and `cli/`. This is why the PDP runs in microseconds, why tests are flake-free, and why upgrading from SQLite to Postgres to a gRPC sidecar is a deployment change, not a rewrite.
271
+
272
+ ---
273
+
274
+ ## Roadmap
275
+
276
+ - **v0.1 (this release)** — MVP: SQLite, YAML policy, allow/deny/approve/dry_run/transform, audit chain, CLI, scripted agent example.
277
+ - **v0.5** — Crash-resume durability, shadow library (shell, SQL, HTTP, AWS), `replay --edit`.
278
+ - **v1.0** — LangGraph / CrewAI / OpenAI Agents SDK / MCP adapters; Postgres store; webhook & Slack approval transports; gRPC sidecar mode; HSM-signed audit.
279
+ - **v1.5** — Control plane: multi-tenant policy distribution, dashboards, cross-run analytics, governance. (Commercial layer.)
280
+
281
+ See `docs/00-execution-plan.md` for the week-by-week plan.
282
+
283
+ ---
284
+
285
+ ## Performance
286
+
287
+ | What | Number |
288
+ |------|--------|
289
+ | Policy evaluation (typical, ≤100 rules) | ~100 µs / call |
290
+ | Policy evaluation (worst case, 1000 rules) | ~1 ms / call |
291
+ | End-to-end overhead per step | ~3 ms (SQLite-bound) |
292
+ | Test suite | 57 tests in 1.1 s |
293
+
294
+ For real agents where each step is a 500 ms – 5 s LLM call, Lynx's overhead is under 1%. Reproducible numbers in [`benchmarks/`](benchmarks/README.md).
295
+
296
+ ---
297
+
298
+ ## Documentation
299
+
300
+ Start here if you're new:
301
+
302
+ | Doc | What it answers |
303
+ |-----|----------------|
304
+ | [Why Lynx](docs/why-lynx.md) | When should I use this? When shouldn't I? |
305
+ | [Getting started](docs/getting-started.md) | 5-minute walkthrough from install to first denial |
306
+ | [Concepts](docs/concepts.md) | Vocabulary: Tool, Policy, Verdict, Run, AuditEvent |
307
+ | [Policy cookbook](docs/cookbook.md) | Copy-pasteable rules for common patterns |
308
+ | [FAQ](docs/faq.md) | Common first-time questions |
309
+
310
+ Reference docs:
311
+
312
+ | Doc | What it covers |
313
+ |-----|----------------|
314
+ | [Data model](docs/01-data-model.md) | The six core types + SQLite schema |
315
+ | [Policy language](docs/02-policy-language.md) | Full YAML grammar + predicates + Python escape hatch |
316
+ | [SDK + CLI](docs/03-sdk-and-cli.md) | The public Python API + every CLI command |
317
+ | [Threat model](docs/threat-model.md) | STRIDE analysis + guarantees + non-goals |
318
+ | [How v0.1 was built](docs/00-execution-plan.md) | The MVP execution plan (historical) |
319
+
320
+ Examples:
321
+
322
+ | Demo | What it shows |
323
+ |------|--------------|
324
+ | [`hello_agent.py`](examples/hello_agent.py) | Minimal scripted agent — the smallest end-to-end loop |
325
+ | [`file_janitor.py`](examples/file_janitor.py) | Real filesystem demo: allow / deny / dry_run with real files |
326
+ | [`refund_agent.py`](examples/refund_agent.py) | Customer-support refund agent — demonstrates `approve_required` |
327
+ | [`claude_janitor.py`](examples/claude_janitor.py) | Real Claude agent driving the file demo |
328
+ | [`openai_janitor.py`](examples/openai_janitor.py) | Same demo, OpenAI GPT |
329
+ | [`fastapi_server.py`](examples/fastapi_server.py) | Drop-in FastAPI integration |
330
+
331
+ See [`examples/README.md`](examples/README.md) for the full index + how to run them.
332
+
333
+ ---
334
+
335
+ ## Status
336
+
337
+ Alpha. APIs may change before v1.0. Use in production at your own risk; report issues liberally.
338
+
339
+ ---
340
+
341
+ ## License
342
+
343
+ Apache 2.0.