tai42-storage-s3
An S3 Storage backend for the TAI ecosystem. It stores text, binary, and media
content in an S3 bucket, implementing the full tai42_contract.storage.Storage
surface — the five text methods (load / list / upload / delete /
delete_dir) plus the binary/media methods (load_bytes / upload_bytes /
stat). S3 stores bytes natively, so the binary methods are true reads/writes
rather than the text bridge.
The TAI ecosystem
TAI is an open-source runtime for MCP tools, agents, and workflows. A Storage
backend is "where content physically lives" — a pluggable provider the runtime's
ResourceManager loads and renders content over. This package is one such
provider (S3); siblings back the same contract with GitHub or the local
filesystem. The ecosystem is open-ended: any package can back the same contract,
so this repo is this provider's own full doc home, and the documentation site
covers the platform-level story:
- Storage & resources concept: https://tai42.ai/concepts/storage-and-resources
- Build a storage provider (author guide): https://tai42.ai/guides/authors/storage-provider
- Ecosystem catalog: https://tai42.ai/reference/catalog
Its only tai-* dependencies are tai42-contract (the Storage ABC, ObjectStat,
assert_not_root, and the tai42_app handle) and tai42-kit (PooledClient,
TaiBaseSettings, and the settings cache). Beyond those it depends on its S3
driver (aioboto3, botocore) and pydantic / pydantic-settings.
The current release line tracks the 7.x contract (tai42-contract>=7,<8).
Install
Requires Python 3.13+. Install from PyPI into the environment that runs the server:
uv add tai42-storage-s3
Or from source — clone this repo and add it as an editable dependency; the
tai42-* dependencies resolve in-tree from the workspace.
git clone https://github.com/tai42ai/tai42 # next to your app checkout
cd /path/to/your/app
uv add --editable ../tai42/plugins/storage-s3
Discovery
The skeleton discovers this backend by importing its package — importing
tai42_storage_s3 fires the @tai42_app.storage.register_storage decorator on
S3Storage as a side-effect (there is no entry-point). Name the package in your
manifest's storage_module field so the runtime imports it at startup:
storage_module: tai42_storage_s3
Configuration
Settings are read from the STORAGE_S3_ environment group (see
S3Settings):
| Env var | Default | Purpose |
|---|---|---|
STORAGE_S3_BUCKET |
— | Target bucket (required) |
STORAGE_S3_ENDPOINT |
— | Custom endpoint (e.g. MinIO); scheme inferred from SECURE if omitted |
STORAGE_S3_ACCESS_KEY |
— | AWS access key id |
STORAGE_S3_SECRET_KEY |
— | AWS secret access key |
STORAGE_S3_SECURE |
true |
Use HTTPS |
STORAGE_S3_REGION |
us-east-1 |
AWS region |
STORAGE_S3_VERIFY_SSL |
true |
Verify TLS certificates |
STORAGE_S3_CONNECT_TIMEOUT |
5 |
Connect timeout (seconds) |
STORAGE_S3_READ_TIMEOUT |
30 |
Read timeout (seconds) |
STORAGE_S3_ADDRESSING_STYLE |
auto |
path / virtual / auto |
STORAGE_S3_REQUEST_CHECKSUM_CALCULATION |
— | when_supported / when_required |
Content-type behavior
upload(text) storesContentType: application/jinja2— a template reads back as its authoring format, not an inferredtext/*.upload_bytesstores the parametrizedcontent_typeas the object'sContentType(omitted whenNone).statreturns the object's storedContentTypeviahead_object, mapping a missing object (404) toFileNotFoundError— no rawClientErroror metadata leaks. Because text uploads storeapplication/jinja2,staton a text template reports that type; it reads as non-media, which is the only thing the content-type gates.
Development
uv venv --python 3.13
uv pip install --no-sources --group dev --editable .
uv run --no-sync pytest --cov --cov-report=term-missing
uv run --no-sync ruff check .
uv run --no-sync ruff format --check .
uv run --no-sync pyright
License
Apache-2.0. See LICENSE and NOTICE.
Metadata
Release files for tai42-storage-s3 1.1.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tai42_storage_s3-1.1.4.tar.gz | 23.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tai42_storage_s3-1.1.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 37.7 kB
Release files / tai42_storage_s3-1.1.4.tar.gz
| Download URL | tai42_storage_s3-1.1.4.tar.gz |
|---|---|
| Size | 23.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0e58d84fd2448d7ac220512c4a5846a59908b684489505963806905a96174e54
|
|
BLAKE2b-256 checksum How to use checksums |
0a48bc12ac42bf869b48fc7868d8292a8d83415f6c36ec349d7238e3f2a16baa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / tai42_storage_s3-1.1.4-py3-none-any.whl
| Download URL | tai42_storage_s3-1.1.4-py3-none-any.whl |
|---|---|
| Size | 14.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b7ac962fa3ca7ee6bbe3f8d2a211f4b75f73691771864506a91eca37ebd98642
|
|
BLAKE2b-256 checksum How to use checksums |
451a37c9a99c4df5a94c9fb534a29b7818c1d18ca11aa6b95412d16fa3a478a8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|