Skip to main content

artifactkit

Installs as agent-artifact-kit, imports as artifactkit the PyPI name is descriptive for discoverability, the import name is short because that's what you actually type in code).

Generic artifact creation harness for agentic workflows. Agents build a declarative content spec; artifactkit renders it to docx/pptx/xlsx/pdf, writes it to a destination (local disk or S3), verifies the write, and returns the location. No agent workflow reimplements this on its own.

Install

pip install agent-artifact-kit[s3]        # local + S3
pip install agent-artifact-kit[all]       # + Strands and MCP adapters

All code below imports the package as artifactkit regardless of which extras you installed.

Development

pip install -e ".[dev]"
pytest tests/ -v
pytest tests/ --cov=artifactkit --cov-report=term-missing   # 93% with all extras installed (131 tests)

See PUBLISHING.md for how to build and release to PyPI, and mkdocs.yml / docs/ for the full documentation site (pip install -e ".[docs]" then mkdocs serve).

Strands hooks

Beyond the tool functions, artifactkit.adapters.strands_hooks (under the [strands] extra) provides three optional hook providers for a Strands agent's lifecycle: policy enforcement (force a destination/theme on every artifactkit call), a tracing bridge (correlate Strands' invocation with artifactkit's operation_id in the logs), and auto-delivery (deliver whatever a code-execution tool wrote, without the agent having to remember to call deliver_files itself). See docs/quickstart.md for usage — all three were verified against the real strands-agents API (event mutability, shared invocation state, result serialization), not assumed from documentation.

Observability

Every call is logged (structured, correlated by an operation_id returned on the result) and, if you supply a MetricsSink, measured. See docs/observability.md for the exact log events, fields, and metric names, or wire in your own sink:

from artifactkit import ArtifactService, MetricsSink

class MySink:
    def increment(self, name, tags=None): ...
    def timing(self, name, duration_ms, tags=None): ...

service = ArtifactService(metrics=MySink())

Plain Python

from artifactkit import (
    ArtifactService, ArtifactFormat, DocumentSpec, Heading, Paragraph,
    destination_from_uri,
)

spec = DocumentSpec(
    title="Q3 Summary",
    blocks=(
        Heading("Overview", level=1),
        Paragraph.of("Revenue grew 12% quarter over quarter."),
    ),
    base_filename="q3_summary",  # optional — bare name, no extension
)

service = ArtifactService()
result = service.create(
    spec,
    ArtifactFormat.DOCX,
    destination=destination_from_uri("s3://reports-bucket/q3"),
    include_presigned_url=True,
    # filename omitted: resolves to "q3_summary.docx" from spec.base_filename,
    # adapted to whatever format is requested. Pass filename= explicitly to
    # override it for this call without changing the spec.
)
print(result.location, result.presigned_url)

Strands agent

from strands import Agent
from artifactkit.adapters.strands_tools import create_docx, create_pptx, create_xlsx, create_pdf

agent = Agent(tools=[create_docx, create_pptx, create_xlsx, create_pdf])

MCP server

python -m artifactkit.adapters.mcp_server

Any MCP-capable agent can then call create_docx / create_pptx / create_xlsx / create_pdf with a JSON spec, a destination_uri, and a filename.

Spec shape

See artifactkit/core/parsing.py for the exact dict shape each tool expects — it's the single source of truth both adapters parse against.

Styling

Bare output from python-docx/pptx/openpyxl looks exactly like what it is: unstyled. Set theme on any structured spec for a named preset (Theme.VIBRANT, Theme.CORPORATE, Theme.MINIMAL) that each backend applies in whatever way fits its format — colored headings and an accent rule in a doc, a gradient hero slide with a decorative shape in a deck, a native Excel Table with banded rows and a colored tab in a workbook. See docs/quickstart.md for examples of all three.

For a real branded .pptx, use template_path instead — inspect_template() reads a template's layouts and placeholders first so you can target them precisely ("idx:1" or an exact placeholder name), rather than guessing at what a custom template contains. theme and template_path don't combine: a template's own design wins.

Sheet.conditional_formats adds real Excel conditional formatting — ColorScaleRule (heatmap), CellValueRule (highlight cells matching a comparison), DataBarRule (in-cell proportional bars) — independent of theme. See docs/quickstart.md.

Arbitrary files (code, images, anything else)

create() is for structured content that needs rendering (docx/pptx/xlsx/pdf). For content you already have, code files, images, data files, whatever, use create_files() instead. It skips rendering entirely and goes straight to write + verify. If you hand it more than 5 files, it bundles them into a single .zip automatically rather than doing one write per file.

Each RawFile takes its content one of two ways:

from artifactkit import ArtifactService, RawFile, FileBundleSpec, destination_from_uri

# In-memory bytes (e.g. code the agent just wrote)
RawFile("main.py", content=b"print('hello')\n")

# A path already on disk (e.g. output from code that ran, a generated
# image, anything already written somewhere) -- read lazily at write
# time, never loaded into memory until it's actually needed.
RawFile("chart.png", source_path="/tmp/agent_run/chart.png")

If a piece of code produced a whole directory of output, skip building RawFiles by hand:

bundle = FileBundleSpec.from_directory("/tmp/agent_run", bundle_filename="run_output")
service = ArtifactService()
result = service.create_files(bundle, destination_from_uri("s3://reports-bucket/runs"))
# 5 or fewer files in the directory -> delivered individually
# 6+ -> bundled into run_output.zip

Via Strands or MCP, this is the deliver_files tool. Each file entry needs exactly one of content_base64 (for content the agent is holding directly) or source_path (for content already on disk, avoids hauling large payloads through the model's context just to hand them back to this tool).

artifactkit never executes code or generates content. It only delivers bytes that already exist. If app.py needs to run and produce files, that execution happens entirely outside this library, with whatever sandboxed runtime the agent already has, and create_files() picks up only once the output exists on disk.

Design notes

  • Render, validate, and write/verify are three separate stages. Only the write/verify stage retries; render and validate failures are deterministic and retrying wastes time.
  • ArtifactValidationError (bad spec/render) and ArtifactWriteError (write couldn't be verified) are distinct exception types so a calling agent can choose the right remediation.
  • Destinations are pluggable via the OutputDestination protocol. Adding GCS/Azure support means one new class, no changes to backends or the service.
  • create() and create_files() share the same write/verify/retry/ presign machinery (ArtifactService._write_verified), the only difference is whether there's a render+validate step first. Arbitrary files skip it because there's no format-specific structure to check on content the caller already fully formed.

Metadata

Release files for agent-artifact-kit 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agent-artifact-kit 0.3.0
File Size Uploaded Provenance
agent_artifact_kit-0.3.0.tar.gz 60.7 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for agent-artifact-kit 0.3.0
File Interpreter ABI Platform
agent_artifact_kit-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 109.7 kB

Release files / agent_artifact_kit-0.3.0.tar.gz

Download URL agent_artifact_kit-0.3.0.tar.gz
Size 60.7 kB
Tags Source
SHA-256 checksum
How to use checksums
af60b12f2f7a8082c4c63a15282e2a50636dde15f3ef2071a354970a5f1e4ea9
BLAKE2b-256 checksum
How to use checksums
db04f3830286d000926cea6ad31f7263599936ea5035cf267f85c79ac55471f7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Release files / agent_artifact_kit-0.3.0-py3-none-any.whl

Download URL agent_artifact_kit-0.3.0-py3-none-any.whl
Size 49.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fe38dee68288fed4617295e765878523e0c0f6daa5f0dee0a0ffb267122e2041
BLAKE2b-256 checksum
How to use checksums
235f2fb1aabb4b9e33e4812634904273216e87ca7de302d91a63ed3e8b986dc6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

Security for agent-artifact-kit 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for agent_artifact_kit-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page