agentino-framework 1.1.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.
- agentino_framework-1.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +40 -0
- agentino_framework-1.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- agentino_framework-1.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +23 -0
- agentino_framework-1.1.0/.github/PULL_REQUEST_TEMPLATE.md +15 -0
- agentino_framework-1.1.0/.github/workflows/ci.yml +55 -0
- agentino_framework-1.1.0/.github/workflows/release.yml +52 -0
- agentino_framework-1.1.0/.gitignore +18 -0
- agentino_framework-1.1.0/CHANGELOG.md +97 -0
- agentino_framework-1.1.0/CLAUDE.md +75 -0
- agentino_framework-1.1.0/CODE_OF_CONDUCT.md +42 -0
- agentino_framework-1.1.0/CONTRIBUTING.md +55 -0
- agentino_framework-1.1.0/DESIGN.md +209 -0
- agentino_framework-1.1.0/LICENSE +202 -0
- agentino_framework-1.1.0/NOTICE +16 -0
- agentino_framework-1.1.0/PKG-INFO +327 -0
- agentino_framework-1.1.0/README.md +239 -0
- agentino_framework-1.1.0/SECURITY.md +42 -0
- agentino_framework-1.1.0/docs/API_EXAMPLES.md +424 -0
- agentino_framework-1.1.0/docs/architecture/ADR-001-async-first.md +72 -0
- agentino_framework-1.1.0/docs/architecture/ADR-002-tool-execution-chain.md +110 -0
- agentino_framework-1.1.0/docs/architecture/ADR-003-yaml-configuration.md +67 -0
- agentino_framework-1.1.0/docs/architecture/ADR-004-jsonl-sessions.md +80 -0
- agentino_framework-1.1.0/docs/architecture/README.md +41 -0
- agentino_framework-1.1.0/docs/cookbook/hooks.md +136 -0
- agentino_framework-1.1.0/docs/cookbook/typed-tool-guards.md +122 -0
- agentino_framework-1.1.0/docs/integration-guide.md +341 -0
- agentino_framework-1.1.0/examples/booking_bot.py +91 -0
- agentino_framework-1.1.0/examples/ci_monitor/agents.yml +38 -0
- agentino_framework-1.1.0/examples/code_review/agents.yml +6 -0
- agentino_framework-1.1.0/examples/code_review/prompts/reviewer.md +18 -0
- agentino_framework-1.1.0/examples/hello.py +35 -0
- agentino_framework-1.1.0/pyproject.toml +88 -0
- agentino_framework-1.1.0/scripts/check_file_sizes.sh +22 -0
- agentino_framework-1.1.0/src/agentino/__init__.py +175 -0
- agentino_framework-1.1.0/src/agentino/__main__.py +502 -0
- agentino_framework-1.1.0/src/agentino/builtin_tools.py +561 -0
- agentino_framework-1.1.0/src/agentino/cli/__init__.py +0 -0
- agentino_framework-1.1.0/src/agentino/cli/json_emitter.py +130 -0
- agentino_framework-1.1.0/src/agentino/cli/renderer.py +390 -0
- agentino_framework-1.1.0/src/agentino/config/__init__.py +182 -0
- agentino_framework-1.1.0/src/agentino/config/agents_yaml.py +399 -0
- agentino_framework-1.1.0/src/agentino/config/pipeline_yaml.py +95 -0
- agentino_framework-1.1.0/src/agentino/config/tools_yaml.py +192 -0
- agentino_framework-1.1.0/src/agentino/config/utils.py +49 -0
- agentino_framework-1.1.0/src/agentino/core/__init__.py +0 -0
- agentino_framework-1.1.0/src/agentino/core/agent.py +738 -0
- agentino_framework-1.1.0/src/agentino/core/context.py +58 -0
- agentino_framework-1.1.0/src/agentino/core/extensions.py +226 -0
- agentino_framework-1.1.0/src/agentino/core/llm.py +589 -0
- agentino_framework-1.1.0/src/agentino/core/message.py +177 -0
- agentino_framework-1.1.0/src/agentino/core/models.py +203 -0
- agentino_framework-1.1.0/src/agentino/core/runner.py +549 -0
- agentino_framework-1.1.0/src/agentino/core/session.py +109 -0
- agentino_framework-1.1.0/src/agentino/core/state.py +120 -0
- agentino_framework-1.1.0/src/agentino/core/tool.py +317 -0
- agentino_framework-1.1.0/src/agentino/extras/__init__.py +0 -0
- agentino_framework-1.1.0/src/agentino/extras/audio.py +221 -0
- agentino_framework-1.1.0/src/agentino/extras/audit.py +109 -0
- agentino_framework-1.1.0/src/agentino/extras/knowledge.py +641 -0
- agentino_framework-1.1.0/src/agentino/extras/memory.py +173 -0
- agentino_framework-1.1.0/src/agentino/extras/skills.py +152 -0
- agentino_framework-1.1.0/src/agentino/extras/usage.py +243 -0
- agentino_framework-1.1.0/src/agentino/pipeline/__init__.py +27 -0
- agentino_framework-1.1.0/src/agentino/pipeline/core.py +179 -0
- agentino_framework-1.1.0/src/agentino/pipeline/staged.py +598 -0
- agentino_framework-1.1.0/src/agentino/providers/__init__.py +0 -0
- agentino_framework-1.1.0/src/agentino/providers/anthropic.py +112 -0
- agentino_framework-1.1.0/src/agentino/providers/codex.py +228 -0
- agentino_framework-1.1.0/src/agentino/py.typed +0 -0
- agentino_framework-1.1.0/src/agentino/reliability/__init__.py +0 -0
- agentino_framework-1.1.0/src/agentino/reliability/compaction.py +147 -0
- agentino_framework-1.1.0/src/agentino/reliability/errors.py +312 -0
- agentino_framework-1.1.0/src/agentino/reliability/resilience.py +242 -0
- agentino_framework-1.1.0/src/agentino/safety/__init__.py +0 -0
- agentino_framework-1.1.0/src/agentino/safety/auth.py +403 -0
- agentino_framework-1.1.0/src/agentino/safety/gates.py +86 -0
- agentino_framework-1.1.0/src/agentino/safety/hooks.py +256 -0
- agentino_framework-1.1.0/src/agentino/safety/sanitize.py +95 -0
- agentino_framework-1.1.0/src/agentino/safety/security.py +152 -0
- agentino_framework-1.1.0/src/agentino/scheduler/README.md +63 -0
- agentino_framework-1.1.0/src/agentino/scheduler/__init__.py +71 -0
- agentino_framework-1.1.0/src/agentino/scheduler/core.py +430 -0
- agentino_framework-1.1.0/src/agentino/scheduler/delivery.py +100 -0
- agentino_framework-1.1.0/src/agentino/scheduler/executor.py +68 -0
- agentino_framework-1.1.0/src/agentino/scheduler/file_store.py +183 -0
- agentino_framework-1.1.0/src/agentino/scheduler/picker.py +51 -0
- agentino_framework-1.1.0/src/agentino/scheduler/sqlite_store.py +112 -0
- agentino_framework-1.1.0/src/agentino/scheduler/store.py +84 -0
- agentino_framework-1.1.0/src/agentino/tools/__init__.py +6 -0
- agentino_framework-1.1.0/src/agentino/tools/std/__init__.py +108 -0
- agentino_framework-1.1.0/src/agentino/tools/std/_agent_memory.py +423 -0
- agentino_framework-1.1.0/src/agentino/tools/std/_file_storage.py +160 -0
- agentino_framework-1.1.0/src/agentino/tools/std/_llm_env.py +32 -0
- agentino_framework-1.1.0/src/agentino/tools/std/_pdf.py +107 -0
- agentino_framework-1.1.0/src/agentino/tools/std/_weather.py +264 -0
- agentino_framework-1.1.0/src/agentino/tools/std/_web_search.py +17 -0
- agentino_framework-1.1.0/src/agentino/tools/std/create_csv.py +54 -0
- agentino_framework-1.1.0/src/agentino/tools/std/create_document.py +236 -0
- agentino_framework-1.1.0/src/agentino/tools/std/create_pdf.py +180 -0
- agentino_framework-1.1.0/src/agentino/tools/std/create_presentation.py +141 -0
- agentino_framework-1.1.0/src/agentino/tools/std/create_spreadsheet.py +135 -0
- agentino_framework-1.1.0/src/agentino/tools/std/fetch_web_data.py +201 -0
- agentino_framework-1.1.0/src/agentino/tools/std/forget.py +25 -0
- agentino_framework-1.1.0/src/agentino/tools/std/get_weather.py +69 -0
- agentino_framework-1.1.0/src/agentino/tools/std/get_weather_forecast.py +71 -0
- agentino_framework-1.1.0/src/agentino/tools/std/list_files.py +52 -0
- agentino_framework-1.1.0/src/agentino/tools/std/read_file.py +217 -0
- agentino_framework-1.1.0/src/agentino/tools/std/read_memory.py +34 -0
- agentino_framework-1.1.0/src/agentino/tools/std/read_rss.py +68 -0
- agentino_framework-1.1.0/src/agentino/tools/std/remember.py +42 -0
- agentino_framework-1.1.0/src/agentino/tools/std/storage.py +145 -0
- agentino_framework-1.1.0/src/agentino/tools/std/translate_text.py +178 -0
- agentino_framework-1.1.0/src/agentino/tools/std/update_memory.py +30 -0
- agentino_framework-1.1.0/src/agentino/transport/__init__.py +21 -0
- agentino_framework-1.1.0/src/agentino/transport/channel.py +236 -0
- agentino_framework-1.1.0/src/agentino/transport/gateway.py +291 -0
- agentino_framework-1.1.0/src/agentino/transport/slack.py +264 -0
- agentino_framework-1.1.0/src/agentino/transport/telegram.py +267 -0
- agentino_framework-1.1.0/src/agentino/transport/webhook.py +77 -0
- agentino_framework-1.1.0/src/agentino/transport/websocket.py +360 -0
- agentino_framework-1.1.0/src/agentino/transport/whatsapp-bridge/bridge.js +306 -0
- agentino_framework-1.1.0/src/agentino/transport/whatsapp-bridge/package.json +17 -0
- agentino_framework-1.1.0/src/agentino/transport/whatsapp.py +188 -0
- agentino_framework-1.1.0/src/agentino/workers/__init__.py +18 -0
- agentino_framework-1.1.0/src/agentino/workers/coordinator.py +320 -0
- agentino_framework-1.1.0/src/agentino/workers/fork.py +204 -0
- agentino_framework-1.1.0/src/agentino/workers/spawn.py +222 -0
- agentino_framework-1.1.0/tests/test_agent.py +260 -0
- agentino_framework-1.1.0/tests/test_anthropic.py +199 -0
- agentino_framework-1.1.0/tests/test_auth.py +164 -0
- agentino_framework-1.1.0/tests/test_builtin_safety.py +202 -0
- agentino_framework-1.1.0/tests/test_cli.py +74 -0
- agentino_framework-1.1.0/tests/test_cli_json_emitter.py +479 -0
- agentino_framework-1.1.0/tests/test_config.py +496 -0
- agentino_framework-1.1.0/tests/test_context.py +122 -0
- agentino_framework-1.1.0/tests/test_docs_stay_true.py +161 -0
- agentino_framework-1.1.0/tests/test_edit_improvements.py +200 -0
- agentino_framework-1.1.0/tests/test_extensions.py +221 -0
- agentino_framework-1.1.0/tests/test_file_storage_provider.py +95 -0
- agentino_framework-1.1.0/tests/test_gates.py +127 -0
- agentino_framework-1.1.0/tests/test_gateway.py +471 -0
- agentino_framework-1.1.0/tests/test_hooks.py +309 -0
- agentino_framework-1.1.0/tests/test_integration.py +428 -0
- agentino_framework-1.1.0/tests/test_knowledge.py +316 -0
- agentino_framework-1.1.0/tests/test_llm.py +344 -0
- agentino_framework-1.1.0/tests/test_llm_lifecycle.py +99 -0
- agentino_framework-1.1.0/tests/test_llm_stream.py +430 -0
- agentino_framework-1.1.0/tests/test_message.py +55 -0
- agentino_framework-1.1.0/tests/test_models.py +116 -0
- agentino_framework-1.1.0/tests/test_new_modules.py +303 -0
- agentino_framework-1.1.0/tests/test_pipeline.py +233 -0
- agentino_framework-1.1.0/tests/test_project_knowledge.py +196 -0
- agentino_framework-1.1.0/tests/test_resilience.py +317 -0
- agentino_framework-1.1.0/tests/test_response_nudges.py +61 -0
- agentino_framework-1.1.0/tests/test_runner.py +141 -0
- agentino_framework-1.1.0/tests/test_sanitize.py +64 -0
- agentino_framework-1.1.0/tests/test_scheduler_stores.py +134 -0
- agentino_framework-1.1.0/tests/test_session.py +131 -0
- agentino_framework-1.1.0/tests/test_smoke.py +208 -0
- agentino_framework-1.1.0/tests/test_spawn.py +255 -0
- agentino_framework-1.1.0/tests/test_staged.py +649 -0
- agentino_framework-1.1.0/tests/test_staged_jumps.py +265 -0
- agentino_framework-1.1.0/tests/test_std_tools_storage_contract.py +41 -0
- agentino_framework-1.1.0/tests/test_tool.py +189 -0
- agentino_framework-1.1.0/tests/test_tool_chain.py +295 -0
- agentino_framework-1.1.0/tests/test_tool_timeout.py +167 -0
- agentino_framework-1.1.0/tests/test_typed_tool_guards.py +207 -0
- agentino_framework-1.1.0/tests/test_usage.py +159 -0
- agentino_framework-1.1.0/tests/test_webhook.py +66 -0
- agentino_framework-1.1.0/tests/test_whatsapp.py +136 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something behaves differently from what the docs say
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: what-happened
|
|
7
|
+
attributes:
|
|
8
|
+
label: What happened
|
|
9
|
+
description: What you did, what you expected, and what you got instead.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: reproduce
|
|
14
|
+
attributes:
|
|
15
|
+
label: Minimal reproduction
|
|
16
|
+
description: >
|
|
17
|
+
The smallest script or config that shows the problem. This is the
|
|
18
|
+
single most useful thing you can include.
|
|
19
|
+
render: python
|
|
20
|
+
validations:
|
|
21
|
+
required: true
|
|
22
|
+
- type: input
|
|
23
|
+
id: version
|
|
24
|
+
attributes:
|
|
25
|
+
label: Version
|
|
26
|
+
description: Release number or commit SHA.
|
|
27
|
+
validations:
|
|
28
|
+
required: true
|
|
29
|
+
- type: input
|
|
30
|
+
id: python
|
|
31
|
+
attributes:
|
|
32
|
+
label: Python version
|
|
33
|
+
placeholder: "3.12.3"
|
|
34
|
+
validations:
|
|
35
|
+
required: true
|
|
36
|
+
- type: textarea
|
|
37
|
+
id: traceback
|
|
38
|
+
attributes:
|
|
39
|
+
label: Traceback or logs
|
|
40
|
+
render: text
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose a change to what Agentino does
|
|
3
|
+
labels: [enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: The problem
|
|
9
|
+
description: >
|
|
10
|
+
What are you trying to do that is awkward or impossible today?
|
|
11
|
+
Describe the situation, not the solution.
|
|
12
|
+
validations:
|
|
13
|
+
required: true
|
|
14
|
+
- type: textarea
|
|
15
|
+
id: proposal
|
|
16
|
+
attributes:
|
|
17
|
+
label: What you have in mind
|
|
18
|
+
description: If you have an API or config shape in mind, sketch it.
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: alternatives
|
|
21
|
+
attributes:
|
|
22
|
+
label: What you tried instead
|
|
23
|
+
description: Workarounds you have used, and why they fall short.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## What this changes
|
|
2
|
+
|
|
3
|
+
<!-- One paragraph. What is different after this lands? -->
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
<!-- The reasoning a reviewer cannot get from the diff. Link the issue if
|
|
8
|
+
there is one. -->
|
|
9
|
+
|
|
10
|
+
## Checklist
|
|
11
|
+
|
|
12
|
+
- [ ] Tests cover the change, and a bug fix has a test that failed before it
|
|
13
|
+
- [ ] `pytest` passes locally
|
|
14
|
+
- [ ] `ruff check .` and `ruff format --check .` pass
|
|
15
|
+
- [ ] Docs updated if behaviour or configuration changed
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ci-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
lint:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.12"
|
|
23
|
+
- run: pip install -e ".[dev]"
|
|
24
|
+
- name: ruff check
|
|
25
|
+
run: ruff check .
|
|
26
|
+
- name: ruff format --check
|
|
27
|
+
run: ruff format --check .
|
|
28
|
+
|
|
29
|
+
test:
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
strategy:
|
|
32
|
+
fail-fast: false
|
|
33
|
+
matrix:
|
|
34
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
- uses: actions/setup-python@v5
|
|
38
|
+
with:
|
|
39
|
+
python-version: ${{ matrix.python-version }}
|
|
40
|
+
- run: pip install -e ".[dev]"
|
|
41
|
+
- name: pytest
|
|
42
|
+
run: pytest tests/ -q
|
|
43
|
+
|
|
44
|
+
build:
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/checkout@v4
|
|
48
|
+
- uses: actions/setup-python@v5
|
|
49
|
+
with:
|
|
50
|
+
python-version: "3.12"
|
|
51
|
+
- run: pip install build twine
|
|
52
|
+
- name: Build the distribution
|
|
53
|
+
run: python -m build
|
|
54
|
+
- name: Check the distribution metadata
|
|
55
|
+
run: twine check dist/*
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write # to attach build artifacts to the release
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
- run: pip install build twine
|
|
20
|
+
- run: python -m build
|
|
21
|
+
- run: twine check dist/*
|
|
22
|
+
- uses: actions/upload-artifact@v4
|
|
23
|
+
with:
|
|
24
|
+
name: dist
|
|
25
|
+
path: dist/
|
|
26
|
+
- name: Attach the artifacts to the release
|
|
27
|
+
if: github.event_name == 'release'
|
|
28
|
+
run: gh release upload "$GITHUB_REF_NAME" dist/*
|
|
29
|
+
env:
|
|
30
|
+
GH_TOKEN: ${{ github.token }}
|
|
31
|
+
|
|
32
|
+
# Publishing is a separate job so a build failure never leaves a partial
|
|
33
|
+
# upload, and so the PyPI credential is scoped to this job alone. It uses
|
|
34
|
+
# Trusted Publishing (OIDC) — there is no API token stored in the repo.
|
|
35
|
+
#
|
|
36
|
+
# Before the first run, configure a pending publisher on PyPI:
|
|
37
|
+
# https://pypi.org/manage/account/publishing/
|
|
38
|
+
# owner: <the GitHub owner> repository: agentino
|
|
39
|
+
# workflow: release.yml environment: pypi
|
|
40
|
+
publish:
|
|
41
|
+
needs: build
|
|
42
|
+
if: github.event_name == 'release'
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
environment: pypi
|
|
45
|
+
permissions:
|
|
46
|
+
id-token: write # required for Trusted Publishing
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/download-artifact@v4
|
|
49
|
+
with:
|
|
50
|
+
name: dist
|
|
51
|
+
path: dist/
|
|
52
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project aims
|
|
5
|
+
to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html) from 1.0
|
|
6
|
+
onward.
|
|
7
|
+
|
|
8
|
+
## [1.1.0] — 2026-08-29
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Apache-2.0 licence, `NOTICE`, contribution guide, security policy, code of
|
|
13
|
+
conduct, and issue and pull-request templates.
|
|
14
|
+
- `agentino.tools.std._llm_env`, one vendor-neutral resolver for the LLM
|
|
15
|
+
endpoint used by the standard tools. Configure with `AGENTINO_BASE_URL` /
|
|
16
|
+
`AGENTINO_API_KEY` or the conventional `OPENAI_*` pair.
|
|
17
|
+
- `__all__` on the public packages, so the supported surface is explicit.
|
|
18
|
+
- `gpt-5.4-codex` in the model registry; it is now the default Codex model.
|
|
19
|
+
- `agentino.tools.std.set_pdf_renderer`, plus a plain reportlab renderer, so
|
|
20
|
+
`create_pdf` works in a standalone install. A host with its own house style
|
|
21
|
+
registers a renderer instead; async renderers are awaited.
|
|
22
|
+
- Storage-contract tests for the file-producing standard tools.
|
|
23
|
+
- `agentino.tools.std.set_file_storage_provider`, so a host application can
|
|
24
|
+
supply its own file storage, plus a local-filesystem default
|
|
25
|
+
(`AGENTINO_FILES_DIR`, falling back to `./.agentino/files`) so the
|
|
26
|
+
file-producing tools work with no configuration.
|
|
27
|
+
|
|
28
|
+
- `py.typed`, so a type checker no longer ignores every annotation in the
|
|
29
|
+
package.
|
|
30
|
+
- Tests that check the documentation against the package: every documented
|
|
31
|
+
import resolves, every file path named in prose exists, and a list of names
|
|
32
|
+
that were promised but never existed cannot reappear.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- Published on PyPI as `agentino-framework`: `pip install agentino-framework`.
|
|
37
|
+
The `agentino` name there belongs to an unrelated project, so the
|
|
38
|
+
distribution carries a second name; the import name is unaffected and
|
|
39
|
+
remains `agentino`. Releases also attach wheels and sdists to the GitHub
|
|
40
|
+
release, and are uploaded by Trusted Publishing rather than a stored token.
|
|
41
|
+
- Licence changed from MIT to Apache-2.0. The repository previously declared
|
|
42
|
+
MIT in metadata with no licence file present.
|
|
43
|
+
- `print_summary` now reports how many stages passed and prints `FAILED`
|
|
44
|
+
rather than `COMPLETE` when any stage failed.
|
|
45
|
+
- CI runs `ruff check` and `ruff format --check`, covers Python 3.10 through
|
|
46
|
+
3.13, and builds the distribution with a `twine` metadata check.
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
|
|
50
|
+
- `builtin_tools` raised `NameError` instead of a readable message when
|
|
51
|
+
`httpx` was missing: the `ImportError` handler called `error_unavailable`
|
|
52
|
+
without importing it.
|
|
53
|
+
- Task notifications dropped the notification body, showing only the
|
|
54
|
+
description.
|
|
55
|
+
- `fetch_web_data` and `translate_text` read different environment variables
|
|
56
|
+
for the same endpoint and defaulted to a hardcoded private host.
|
|
57
|
+
- Four standard tools imported modules belonging to the workspace runtime
|
|
58
|
+
built *on top of* this framework — `protocols` in three, and
|
|
59
|
+
`helpers.documents.branded_pdf` in `create_pdf`. A standalone install
|
|
60
|
+
had no such module, so `read_file`, `list_files` and file creation raised
|
|
61
|
+
ImportError. The dependency is now inverted: the host registers storage.
|
|
62
|
+
- A tenant id of `..` traversed out of the storage root. Path segments that
|
|
63
|
+
are only dots are replaced, not just character-substituted.
|
|
64
|
+
|
|
65
|
+
- `examples/hello.py` and `examples/booking_bot.py` called `agent.run(...)`
|
|
66
|
+
without awaiting it, so both printed a coroutine object and never reached a
|
|
67
|
+
model. The smallest example in the repository did not work.
|
|
68
|
+
- `discover_tools_from_dir` is exported publicly but was annotated `Path` and
|
|
69
|
+
called `.is_dir()` directly, so the natural call with a string raised
|
|
70
|
+
`AttributeError`. Every caller inside the package passed a `Path`, which is
|
|
71
|
+
why it went unnoticed.
|
|
72
|
+
- The transport package documented `pip install agentino[telegram]`, `[slack]`
|
|
73
|
+
and `[serve]`. None of those extras existed, so each of those commands
|
|
74
|
+
failed.
|
|
75
|
+
- The README declared MIT while `LICENSE`, `NOTICE` and `pyproject` all
|
|
76
|
+
declare Apache-2.0 — the one statement that would have mattered to someone
|
|
77
|
+
deciding whether they could use this.
|
|
78
|
+
- The README promised `Runner.run_sync`. There is no synchronous wrapper
|
|
79
|
+
anywhere; the core is async throughout.
|
|
80
|
+
- `LLMClient`'s docstring listed `OPENAI_BASE_URL` as a fallback for the
|
|
81
|
+
endpoint. It is not read at all, so setting it silently did nothing.
|
|
82
|
+
- `SECURITY.md` described the project as pre-1.0 at version 1.1.0, in the
|
|
83
|
+
section a reader consults to learn which releases are patched.
|
|
84
|
+
- The README's layout omitted `tools/`, the built-in tools package.
|
|
85
|
+
|
|
86
|
+
### Removed
|
|
87
|
+
|
|
88
|
+
- `browse_web` and `crawl_page`. Both imported `helpers.crawler`, a module
|
|
89
|
+
belonging to a host application that has never existed in this package, so
|
|
90
|
+
they returned an error string on every call and no test covered them. The
|
|
91
|
+
`browser` extra goes with them.
|
|
92
|
+
- An internal cross-repository planning document.
|
|
93
|
+
- CI exclusions for two test files whose 30 tests pass.
|
|
94
|
+
|
|
95
|
+
## [1.1.0] and earlier
|
|
96
|
+
|
|
97
|
+
Released before this changelog was kept. See the git history.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# CLAUDE.md — Agentino
|
|
2
|
+
|
|
3
|
+
Notes for coding agents (and humans) working in this repository.
|
|
4
|
+
|
|
5
|
+
## What this is
|
|
6
|
+
|
|
7
|
+
A lightweight Python agent framework — 88 modules, about 12,000 lines of
|
|
8
|
+
code. An agent is a loop:
|
|
9
|
+
send messages and tool schemas to an LLM; if it calls a tool, run the tool and
|
|
10
|
+
loop; if it returns text, stop. Everything else here is in service of that.
|
|
11
|
+
|
|
12
|
+
## Setup
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
python -m venv .venv && source .venv/bin/activate
|
|
16
|
+
pip install -e ".[dev]"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pytest tests/ -q # the suite CI runs
|
|
23
|
+
ruff check src/ tests/ # lint — must be clean
|
|
24
|
+
ruff format --check src/ tests/ # formatting — must be clean
|
|
25
|
+
python -m build # build the wheel
|
|
26
|
+
|
|
27
|
+
agentino chat # REPL
|
|
28
|
+
agentino run agents.yml # run agents from config
|
|
29
|
+
agentino run agents.yml -m "hi" # one-shot message
|
|
30
|
+
agentino run agents.yml --gateway # multi-channel gateway
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Layout
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
src/agentino/
|
|
37
|
+
├── core/ Agent, Runner, LLMClient, Tool, Message, Context, State, Session
|
|
38
|
+
├── config/ YAML loaders for agents, pipelines, tools
|
|
39
|
+
├── pipeline/ Pipeline and StagedPipeline (multi-stage flows with verdicts)
|
|
40
|
+
├── safety/ GateManager, HookManager, sanitizers
|
|
41
|
+
├── reliability/ retry and backoff, history compaction, the error taxonomy
|
|
42
|
+
├── extras/ knowledge base, memory, audio, skills, usage tracking
|
|
43
|
+
├── providers/ pluggable LLM backends
|
|
44
|
+
├── scheduler/ CronScheduler and the JobStore protocol
|
|
45
|
+
├── transport/ outbound channels — Telegram, Slack, WhatsApp, WebSocket
|
|
46
|
+
├── workers/ fork_agent and make_spawn_tool for multi-agent work
|
|
47
|
+
├── tools/std/ the standard tool catalogue
|
|
48
|
+
└── cli/ REPL renderer and the JSON event emitter
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`from agentino import ...` is the public API and is what `__all__` in
|
|
52
|
+
`src/agentino/__init__.py` declares. Deeper paths such as
|
|
53
|
+
`from agentino.safety.gates import GateManager` are how internal packages talk
|
|
54
|
+
to each other; treat them as unstable.
|
|
55
|
+
|
|
56
|
+
## Conventions that matter here
|
|
57
|
+
|
|
58
|
+
- **The framework provides mechanisms, not policies.** Anything that encodes
|
|
59
|
+
one application's behaviour — prompt wording, thresholds, a specific tool's
|
|
60
|
+
name, a natural language — belongs to that application, not here. If you
|
|
61
|
+
find yourself adding a rule that only makes sense for one deployment, add a
|
|
62
|
+
seam instead and let config supply the rule.
|
|
63
|
+
- **No hardcoded endpoints or credentials.** Configuration comes from the
|
|
64
|
+
environment; `agentino.tools.std._llm_env` resolves the LLM endpoint and is
|
|
65
|
+
the only place that should know a default host.
|
|
66
|
+
- **Tests come with the change.** A bug fix without a test that fails before
|
|
67
|
+
it is not finished.
|
|
68
|
+
- **Lint is enforced.** CI runs `ruff check` and `ruff format --check`, so a
|
|
69
|
+
formatting argument is never worth having.
|
|
70
|
+
|
|
71
|
+
## Releasing
|
|
72
|
+
|
|
73
|
+
Version lives in `pyproject.toml`. The distribution is published as
|
|
74
|
+
`agentino-framework` because the `agentino` name on PyPI belongs to an
|
|
75
|
+
unrelated project; the import name is unaffected.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our pledge
|
|
4
|
+
|
|
5
|
+
We want participation in this project to be a harassment-free experience for
|
|
6
|
+
everyone, whatever their age, body size, disability, ethnicity, sex
|
|
7
|
+
characteristics, gender identity and expression, level of experience,
|
|
8
|
+
education, socio-economic status, nationality, personal appearance, race,
|
|
9
|
+
religion, or sexual identity and orientation.
|
|
10
|
+
|
|
11
|
+
## Our standards
|
|
12
|
+
|
|
13
|
+
Things that help:
|
|
14
|
+
|
|
15
|
+
- being welcoming and respectful of differing viewpoints
|
|
16
|
+
- accepting constructive criticism gracefully
|
|
17
|
+
- focusing on what is best for the project
|
|
18
|
+
- showing empathy toward other people
|
|
19
|
+
|
|
20
|
+
Things that are not acceptable:
|
|
21
|
+
|
|
22
|
+
- sexualised language or imagery, and unwelcome sexual attention
|
|
23
|
+
- trolling, insults, derogatory comments, and personal or political attacks
|
|
24
|
+
- public or private harassment
|
|
25
|
+
- publishing someone's private information without explicit permission
|
|
26
|
+
|
|
27
|
+
## Enforcement
|
|
28
|
+
|
|
29
|
+
Report unacceptable behaviour by contacting the maintainer,
|
|
30
|
+
[@islavutin-oss](https://github.com/islavutin-oss), through a GitHub private message
|
|
31
|
+
or a private security advisory on this repository. All reports are reviewed
|
|
32
|
+
and investigated, and will be kept confidential.
|
|
33
|
+
|
|
34
|
+
Maintainers may remove comments, commits, code, issues and other
|
|
35
|
+
contributions that violate this Code of Conduct, and may ban contributors
|
|
36
|
+
temporarily or permanently for behaviour they judge inappropriate,
|
|
37
|
+
threatening, offensive or harmful.
|
|
38
|
+
|
|
39
|
+
## Attribution
|
|
40
|
+
|
|
41
|
+
Adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
|
|
42
|
+
version 1.4.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Contributing to Agentino
|
|
2
|
+
|
|
3
|
+
Thanks for taking the time. This is a small project, so the process is short.
|
|
4
|
+
|
|
5
|
+
## Before you start
|
|
6
|
+
|
|
7
|
+
For anything beyond a bug fix or a typo, **open an issue first**. It is much
|
|
8
|
+
less painful to disagree about an approach in an issue than in a finished
|
|
9
|
+
pull request.
|
|
10
|
+
|
|
11
|
+
## Getting set up
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git clone https://github.com/islavutin-oss/agentino.git
|
|
15
|
+
cd agentino
|
|
16
|
+
python -m venv .venv && source .venv/bin/activate
|
|
17
|
+
pip install -e ".[dev]"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Run the tests and the linter:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pytest tests/ -q
|
|
24
|
+
ruff check .
|
|
25
|
+
ruff format --check .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
CI runs exactly these, on Python 3.10 through 3.13.
|
|
29
|
+
|
|
30
|
+
## What a good pull request looks like
|
|
31
|
+
|
|
32
|
+
- **One change per pull request.** Unrelated fixes bundled together are hard
|
|
33
|
+
to review and harder to revert.
|
|
34
|
+
- **Tests come with the change.** A bug fix should include a test that fails
|
|
35
|
+
before it and passes after.
|
|
36
|
+
- **The suite is green.** Not "green except for a flaky one" — if something
|
|
37
|
+
is flaky, that is worth an issue of its own.
|
|
38
|
+
- **Commit messages say what changed and why.** The subject line is
|
|
39
|
+
imperative and under about 72 characters; the body explains the reasoning
|
|
40
|
+
a reviewer cannot get from the diff.
|
|
41
|
+
|
|
42
|
+
We use [Conventional Commits](https://www.conventionalcommits.org) prefixes:
|
|
43
|
+
`feat:`, `fix:`, `docs:`, `test:`, `refactor:`, `chore:`, `ci:`.
|
|
44
|
+
|
|
45
|
+
## Style
|
|
46
|
+
|
|
47
|
+
The linter settles formatting arguments, so there is nothing to debate:
|
|
48
|
+
`ruff format` owns line width, `ruff check` owns the rest. Type hints on
|
|
49
|
+
public functions. Comments should explain why something is the way it is —
|
|
50
|
+
the code already says what it does.
|
|
51
|
+
|
|
52
|
+
## Licensing
|
|
53
|
+
|
|
54
|
+
Contributions are accepted under the [Apache License 2.0](LICENSE), the same
|
|
55
|
+
licence the project ships under. There is no CLA.
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Design Document
|
|
2
|
+
|
|
3
|
+
## Vision
|
|
4
|
+
|
|
5
|
+
Lightweight Python agent framework. YAML config → agents → run.
|
|
6
|
+
|
|
7
|
+
Apache-2.0 licensed. Provider-agnostic. Core deps: httpx + pyyaml.
|
|
8
|
+
|
|
9
|
+
## Core Principle
|
|
10
|
+
|
|
11
|
+
**An agent is a loop.** Send messages + tools to an LLM. If the LLM calls a tool, execute it and loop. If the LLM returns text, you're done.
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
┌─────────────────────────────────────────────┐
|
|
17
|
+
│ Layer 4: Transport │
|
|
18
|
+
│ Telegram, Slack, WhatsApp, WebSocket │
|
|
19
|
+
├─────────────────────────────────────────────┤
|
|
20
|
+
│ Layer 3: Orchestration │
|
|
21
|
+
│ StagedPipeline, RouterPipeline, Parallel │
|
|
22
|
+
├─────────────────────────────────────────────┤
|
|
23
|
+
│ Layer 2: Persistence │
|
|
24
|
+
│ Session (JSONL), KnowledgeBase (TF-IDF + │
|
|
25
|
+
│ dense embeddings, SQLite cache) │
|
|
26
|
+
├─────────────────────────────────────────────┤
|
|
27
|
+
│ Layer 1: Core │
|
|
28
|
+
│ Agent, @tool, LLMClient, Config, Events │
|
|
29
|
+
└─────────────────────────────────────────────┘
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Each layer independently usable. All layers optional except Core.
|
|
33
|
+
|
|
34
|
+
## Config-Driven Agents
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
# agents.yml
|
|
38
|
+
providers:
|
|
39
|
+
router:
|
|
40
|
+
base_url: https://router.example.com/v1
|
|
41
|
+
api_key: ${AGENTINO_API_KEY}
|
|
42
|
+
provider: openai-codex
|
|
43
|
+
|
|
44
|
+
agents:
|
|
45
|
+
coder:
|
|
46
|
+
model: router/gpt-5.4-codex
|
|
47
|
+
soul: ./SOUL.md
|
|
48
|
+
tools_dir: ./tools
|
|
49
|
+
tools: [read_file, write_file, shell, grep, stage_verdict]
|
|
50
|
+
temperature: 0.3
|
|
51
|
+
max_turns: 50
|
|
52
|
+
|
|
53
|
+
gateway:
|
|
54
|
+
slack:
|
|
55
|
+
bot_token: ${SLACK_BOT_TOKEN}
|
|
56
|
+
app_token: ${SLACK_APP_TOKEN}
|
|
57
|
+
agent: coder
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`load_config("agents.yml")` auto-detects `stages.yml` → creates StagedPipeline.
|
|
61
|
+
|
|
62
|
+
## Agent Pattern
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
my-agent/
|
|
66
|
+
├── SOUL.md # identity + rules
|
|
67
|
+
├── agents.yml # model, tools, provider config
|
|
68
|
+
├── stages.yml # pipeline stages (optional)
|
|
69
|
+
└── tools/ # custom tools (optional)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Staged Pipeline
|
|
73
|
+
|
|
74
|
+
Multi-stage execution with deterministic control flow:
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
# stages.yml
|
|
78
|
+
global_max_cycles: 20
|
|
79
|
+
|
|
80
|
+
stages:
|
|
81
|
+
- name: IMPLEMENT
|
|
82
|
+
prompt: "Implement the plan..."
|
|
83
|
+
verdict_tool: stage_verdict
|
|
84
|
+
repeatable: true
|
|
85
|
+
on_fail: retry
|
|
86
|
+
|
|
87
|
+
- name: TEST
|
|
88
|
+
prompt: "Run tests..."
|
|
89
|
+
verdict_tool: stage_verdict
|
|
90
|
+
repeatable: true
|
|
91
|
+
on_fail: IMPLEMENT # jump back on failure
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- `verdict_tool` — structured ACCEPT/REJECT/FAIL signals
|
|
95
|
+
- `repeatable` + `max_cycles` — retry stages
|
|
96
|
+
- `on_fail: "STAGE_NAME"` — jump to named stage (loops)
|
|
97
|
+
- `global_max_cycles` — hard budget
|
|
98
|
+
- Fresh Agent context per stage
|
|
99
|
+
- `on_event` callback for all pipeline events
|
|
100
|
+
|
|
101
|
+
## Router Pipeline
|
|
102
|
+
|
|
103
|
+
LLM-based intent classification → route to specialist agents:
|
|
104
|
+
|
|
105
|
+
```yaml
|
|
106
|
+
pipeline:
|
|
107
|
+
type: router
|
|
108
|
+
router: classifier
|
|
109
|
+
routes:
|
|
110
|
+
support: support_agent
|
|
111
|
+
billing: billing_agent
|
|
112
|
+
default: support
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Message Hook
|
|
116
|
+
|
|
117
|
+
App-level intent routing:
|
|
118
|
+
|
|
119
|
+
```yaml
|
|
120
|
+
message_hook: my_module # loads my_module.classify_and_route
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`async (runner, agent, message, session) -> str | None`
|
|
124
|
+
Return str = reply (skip pipeline). Return None = run pipeline.
|
|
125
|
+
|
|
126
|
+
## Built-in Tools
|
|
127
|
+
|
|
128
|
+
`shell`, `read_file`, `write_file`, `edit_file`, `list_files`, `grep`, `search_files`, `stage_verdict`
|
|
129
|
+
|
|
130
|
+
Shell timeout: `AGENTINO_SHELL_TIMEOUT` env var (default: no limit).
|
|
131
|
+
|
|
132
|
+
## Knowledge Base
|
|
133
|
+
|
|
134
|
+
Hybrid TF-IDF + dense embeddings. Auto-indexed from `.agentino/`.
|
|
135
|
+
Tools: `search_knowledge`, `save_knowledge`, `delete_knowledge`.
|
|
136
|
+
|
|
137
|
+
## Gateway
|
|
138
|
+
|
|
139
|
+
Single process, multiple channels: Telegram, Slack, WhatsApp, WebSocket.
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
agentino run agents.yml --gateway
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## File Layout
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
src/agentino/ ~12,000 LOC
|
|
149
|
+
├── agent.py Core loop + resilience
|
|
150
|
+
├── tool.py @tool decorator, schema gen
|
|
151
|
+
├── llm.py OpenAI-compatible client
|
|
152
|
+
├── config.py YAML loader, auto-detect stages.yml
|
|
153
|
+
├── staged.py StagedPipeline
|
|
154
|
+
├── pipeline.py RouterPipeline, sequence, parallel
|
|
155
|
+
├── runner.py Runner, message_hook, HTTP, REPL
|
|
156
|
+
├── cli_renderer.py Terminal rendering
|
|
157
|
+
├── builtin_tools.py shell, read_file, grep, etc.
|
|
158
|
+
├── knowledge.py Hybrid search KB
|
|
159
|
+
├── session.py JSONL persistence
|
|
160
|
+
├── resilience.py Retry, compaction, truncation
|
|
161
|
+
├── message.py Message, ToolCall, Event
|
|
162
|
+
├── auth.py Multi-provider auth
|
|
163
|
+
├── context.py Thread-local context
|
|
164
|
+
├── spawn.py Subagent spawning
|
|
165
|
+
├── audio.py STT transcription
|
|
166
|
+
├── usage.py Token tracking
|
|
167
|
+
└── transport/ Channel adapters
|
|
168
|
+
├── gateway.py
|
|
169
|
+
├── telegram.py
|
|
170
|
+
├── slack.py
|
|
171
|
+
├── websocket.py
|
|
172
|
+
├── webhook.py
|
|
173
|
+
└── whatsapp.py
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
27 test files. Python >=3.10.
|
|
177
|
+
|
|
178
|
+
## Dependencies
|
|
179
|
+
|
|
180
|
+
| Install | Adds |
|
|
181
|
+
|---------|------|
|
|
182
|
+
| `pip install agentino` | httpx, pyyaml |
|
|
183
|
+
| `agentino[memory]` | + numpy |
|
|
184
|
+
| `agentino[telegram]` | + aiogram |
|
|
185
|
+
| `agentino[slack]` | + slack-bolt, aiohttp |
|
|
186
|
+
| `agentino[serve]` | + uvicorn, starlette |
|
|
187
|
+
| `agentino[all]` | everything |
|
|
188
|
+
|
|
189
|
+
## Design Decisions
|
|
190
|
+
|
|
191
|
+
- YAML-only config (see ADR-003)
|
|
192
|
+
- OpenAI-compatible API (Codex, OpenAI, Anthropic, any endpoint)
|
|
193
|
+
- Async-first architecture (see ADR-001)
|
|
194
|
+
- Tool execution chain: validate → permission → execute (see ADR-002)
|
|
195
|
+
- FinalResult for deterministic structured outputs
|
|
196
|
+
- JSONL sessions (see ADR-004)
|
|
197
|
+
- Framework provides mechanisms, not policies — no app logic in core
|
|
198
|
+
- stages.yml = pure pipeline config, app routing via message_hook
|
|
199
|
+
|
|
200
|
+
## Architecture Decision Records
|
|
201
|
+
|
|
202
|
+
See `docs/architecture/` for detailed ADRs on major design choices:
|
|
203
|
+
|
|
204
|
+
| ADR | Title | Summary |
|
|
205
|
+
|-----|-------|---------|
|
|
206
|
+
| ADR-001 | Async-First | All core APIs are async for concurrent I/O efficiency |
|
|
207
|
+
| ADR-002 | Tool Execution Chain | 3-stage validation → permission → execution pattern |
|
|
208
|
+
| ADR-003 | YAML-Only | Single configuration format for simplicity |
|
|
209
|
+
| ADR-004 | JSONL Sessions | Line-based conversation persistence for git-friendliness |
|