Artifacts¶
Artifacts are explicit outputs produced by agents during a session. While conversation text is transient, artifacts are tangible assets like generated CSV files, compiled source code, data reports, or created images.
This page consolidates artifact guidance: lifecycle APIs, storage backends, runner setup, agent helpers, tool usage, and the HTTP API surface.
Lifecycle and core APIs¶
Artifacts are scoped to app + user + session and support versioning. The core service interface includes:
- Save (
SaveArtifactAsync) - Load (
LoadArtifactAsync, latest or specific version) - List keys (
ListArtifactKeysAsync) - List versions (
ListVersionsAsync,ListArtifactVersionsAsync) - Delete (
DeleteArtifactAsync)
These APIs are implemented by InMemoryArtifactService, FileArtifactService, and GcsArtifactService.
Artifact services¶
The ADK includes several built-in services to handle artifact storage depending on your environment:
| Service | Storage Location | Best For |
|---|---|---|
InMemoryArtifactService |
Memory | Unit testing or ephemeral CLI applications. |
FileArtifactService |
Local Filesystem | Desktop applications or local development. |
GcsArtifactService |
Google Cloud Storage | Production cloud environments (supports versioning). |
Configuring artifacts in the runner¶
Agents rely on the Runner to provide access to the Artifact Service. Configure it when bootstrapping your application:
using GoogleAdk.Core.Runner;
using GoogleAdk.Core.Artifacts;
// Configure the runner to save artifacts to the local "output_files" folder
var runner = new Runner(new RunnerConfig
{
AppName = "my_app",
Agent = myAgent,
ArtifactService = new FileArtifactService("output_files")
});
Agent helpers (AgentContext)¶
Inside tools or agent callbacks, use AgentContext helpers to persist artifacts and automatically emit artifact deltas:
// Saves the artifact and records the new version in EventActions.ArtifactDelta
await context.SaveArtifactAsync("summary.txt", new Part { Text = "Final report." });
// Loads an artifact (latest by default)
var part = await context.LoadArtifactAsync("summary.txt");
SaveArtifactAsync updates the ArtifactDelta collection so streaming clients can render artifacts as they appear.
User uploads and SaveFilesAsArtifactsPlugin¶
When using the web UI or a client that sends InlineData as part of a user message, the SaveFilesAsArtifactsPlugin intercepts those parts, stores them as artifacts, and replaces the inline data with a FileData reference (artifact://...). This is primarily for user uploads, not for model output.
If you want model-produced files to become artifacts, use AgentContext.SaveArtifactAsync from a tool or agent callback.
Saving and loading artifacts directly¶
If a tool or external process needs to read or write artifacts without AgentContext, use the service APIs directly:
using GoogleAdk.Core.Artifacts;
using GoogleAdk.Core.Abstractions.Models;
var service = new FileArtifactService("my_artifacts_folder");
await service.SaveArtifactAsync(new SaveArtifactRequest
{
AppName = "my_app",
UserId = "user_123",
SessionId = "session_456",
Filename = "summary_report.txt",
Artifact = new Part { Text = "This is the final summary output." }
});
var loadedPart = await service.LoadArtifactAsync(new LoadArtifactRequest
{
AppName = "my_app",
UserId = "user_123",
SessionId = "session_456",
Filename = "summary_report.txt"
});
Console.WriteLine(loadedPart?.Text);
Loading artifacts from tools¶
The built-in load_artifacts tool can be exposed to models when you want the model to read artifacts (for example, a user upload saved by the UI):
var agent = new LlmAgent(new LlmAgentConfig
{
Name = "artifact_reader",
Model = "gemini-2.5-flash",
Tools = [new LoadArtifactsTool()]
});
The tool returns text directly when available and provides a short descriptor for binary content.
HTTP API: artifact routes¶
The API server exposes REST endpoints for artifact retrieval and listing. The key routes are:
| Method | Route | Description |
|---|---|---|
GET |
/apps/{appName}/users/{userId}/sessions/{sessionId}/artifacts |
List all artifacts for a session. |
GET |
/apps/{appName}/users/{userId}/sessions/{sessionId}/artifacts/{artifactName}/versions |
List all versions of a specific artifact. |
GET |
/apps/{appName}/users/{userId}/sessions/{sessionId}/artifacts/{artifactName}/versions/{versionId} |
Retrieve a specific version of an artifact. |
GET |
/apps/{appName}/users/{userId}/sessions/{sessionId}/artifacts/{artifactName}/versions/{versionId}/metadata |
Retrieve metadata for a specific version. |
GET |
/apps/{appName}/users/{userId}/sessions/{sessionId}/artifacts/{artifactName}/versions/metadata |
Retrieve metadata for all versions. |
DELETE |
/apps/{appName}/users/{userId}/sessions/{sessionId}/artifacts/{artifactName} |
Delete an artifact and all its versions. |
If a stored artifact only has text, the API wraps it into InlineData so the web UI can treat it like a file download.
Streaming semantics and ArtifactDelta¶
When running via SSE (/run_sse), events that contain both content and ArtifactDelta are split into two SSE events to prevent double-rendering in the web UI. Clients should handle a pure artifact event (no content) and render newly available artifacts based on the ArtifactDelta map.
Sample: ArtifactsWeb¶
For a complete end-to-end example (uploads, storage, and display), see GoogleAdk.Samples.ArtifactsWeb.