Using Artifact Stores to Save Agent Outputs with aisuite: A Complete Guide
To save large agent outputs with aisuite, pass an InMemoryArtifactStore or FileArtifactStore to Runner.run_sync() via the artifact_store parameter; the framework automatically converts oversized strings into lightweight artifact references while storing the full data for later retrieval.
When building AI agents with aisuite, handling large command outputs or file contents can quickly consume expensive LLM context windows. The aisuite framework, developed by Andrew Ng's team, provides a robust artifact store abstraction that persists heavyweight data outside the model's prompt while maintaining traceability. Using artifact stores to save agent outputs with aisuite allows you to cap message sizes, reduce API costs, and retain full output history for debugging or auditing.
How Artifact Stores Work in aisuite
The artifact system centers on ArtifactRef and Artifact classes defined in aisuite/agents/artifact_store.py. These lightweight metadata objects identify stored blobs without burdening the conversation context.
Core Storage Implementations
aisuite offers two concrete store implementations:
InMemoryArtifactStore– Stores artifacts in a Python dictionary (lines 68-94 ofartifact_store.py). Ideal for testing and ephemeral workflows where persistence across restarts is unnecessary.FileArtifactStore– Persists artifacts under a configurable directory hierarchy (lines 111-148 ofartifact_store.py). Suitable for production traces that must survive process restarts.
Both implementations expose put(), get(), and delete() methods for artifact lifecycle management.
The Automatic Artifactization Flow
When you enable artifact storage, aisuite orchestrates the following flow during agent execution:
-
Initialization – You inject the store via
Runner.run_sync(..., artifact_store=store)(lines 49-58 ofrunner.py). The runner attaches the store to the active run context (lines 68-71). -
Hydration – Before the first LLM request,
hydrate_messagesinaisuite/agents/artifacts.pyresolves any existingartifact_refobjects back to real text using the store, enabling seamless run resumption. -
Size Threshold Checking – During tool execution,
tools.py(lines 76-84) callsartifactize_valuefromartifacts.py(lines 45-78). If a string exceeds the default 20,000-character threshold, the framework stores the full value and replaces it with a reference object containing a preview snippet. -
Trace Emission – Trace events carry the artifact reference instead of raw payloads. The web UI viewer (
aisuite/tracing/viewer.py) can later retrieve the full content viaartifact_store.get(ref).text().
Saving Agent Outputs with In-Memory Storage
For development and testing, use InMemoryArtifactStore to capture large outputs without disk I/O:
import aisuite as ai
from aisuite.agents import Agent, Runner
# Initialize an in-memory store
artifact_store = ai.InMemoryArtifactStore()
# Create an agent with shell tools
agent = ai.Agent(
name="demo",
model="openai:gpt-4o",
tools=[*ai.toolkits.shell(cwd=".", allowed_commands=["python3"])],
instructions="Run the requested command and return the full output.",
)
# Execute a command producing >20k characters
result = Runner.run_sync(
agent,
"Run `python3 -c 'print(\"x\" * 21001)'`",
artifact_store=artifact_store,
)
# The trace contains an artifact reference; retrieve the full data
artifact_ref = ai.ArtifactRef.from_dict(
result.steps[-1].data["result_artifacts"][0]["artifact_ref"]
)
large_output = artifact_store.get(artifact_ref).text()
print(f"Stored artifact size: {len(large_output)}")
This pattern is verified in tests/toolkits/test_shell.py (lines 165-190), which validates that large shell outputs are automatically artifactized and retrievable via artifact_store.get(ref).
Persisting Agent Outputs to Disk
To survive process restarts, switch to FileArtifactStore:
# Create a persistent store at a specific root directory
artifact_store = ai.FileArtifactStore(".aisuite/artifacts")
# Use the same Runner.run_sync() call as before
result = Runner.run_sync(
agent,
"Run `python3 -c 'print(\"x\" * 21001)'`",
artifact_store=artifact_store,
)
The file store writes each artifact to .aisuite/artifacts/<artifact_id>/data with an accompanying metadata.json. The directory layout enables the web UI to serve /api/artifacts/<artifact_id> endpoints for downloading or previewing historical outputs.
Retrieving Artifacts from the Trace
Whether using in-memory or file-based storage, you can access stored data programmatically via the artifact reference:
# Extract the reference from the trace steps
ref_dict = result.steps[-1].data["result_artifacts"][0]["artifact_ref"]
artifact_ref = ai.ArtifactRef.from_dict(ref_dict)
# Retrieve the full content
artifact = artifact_store.get(artifact_ref)
full_text = artifact.text()
The Artifact object provides a .text() method to decode the stored bytes, while the reference itself contains only a preview string and metadata, keeping LLM context windows lean.
Summary
- Inject the store – Pass
artifact_storetoRunner.run_sync()orRunner.run()to enable automatic output persistence. - Choose your backend – Use
InMemoryArtifactStorefor fast, temporary testing; useFileArtifactStorefor durable, production-grade storage. - Automatic thresholding – Outputs exceeding 20,000 characters are automatically converted to
ArtifactRefobjects viaartifactize_valueinaisuite/agents/artifacts.py. - Programmatic access – Retrieve full content anytime using
artifact_store.get(ref).text(), while traces store only lightweight references. - UI integration – The web viewer automatically resolves artifact references served from
FileArtifactStoredirectories.
Frequently Asked Questions
What is the default size threshold for automatic artifactization in aisuite?
The default threshold is 20,000 characters. When a tool returns a string exceeding this length, aisuite's tools.py automatically invokes artifactize_value to store the data and replace it with a reference. This threshold prevents large command outputs from bloating the LLM context window while preserving the data in the artifact store.
Can I use artifact stores with async runners?
Yes. The artifact_store parameter works identically in Runner.run() (async) and Runner.run_sync() (synchronous). The store is attached to the run context in runner.py (lines 68-71) regardless of which execution mode you choose, ensuring consistent hydration and dehydration of messages.
How does the web UI access stored artifacts?
When using FileArtifactStore, artifacts are written to .aisuite/artifacts/<artifact_id>/data with metadata.json sidecars. The viewer implementation in aisuite/tracing/viewer.py exposes these via HTTP endpoints at /api/artifacts/<artifact_id>, allowing the frontend to fetch full content on demand while displaying previews in the trace timeline.
Is it safe to delete artifacts manually from the file system?
While FileArtifactStore provides a delete() method that safely handles missing files, manual deletion is generally safe if you remove the entire <artifact_id> directory. However, this will break trace references pointing to that artifact. Always use the store's delete(ref) method to ensure consistency between the file system and any in-memory indices.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →