Service Implementations
Different artifact service backends and their configurations for various deployment scenarios
The artifact system is built around the BaseArtifactService
interface, which allows you to choose different storage backends based on your requirements. Each implementation offers different trade-offs between performance, persistence, and scalability.
BaseArtifactService Interface
All artifact services implement the same core interface:
import type { Part } from '@google/genai';
interface BaseArtifactService {
saveArtifact(args: {
appName: string;
userId: string;
sessionId: string;
filename: string;
artifact: Part;
}): Promise<number>;
loadArtifact(args: {
appName: string;
userId: string;
sessionId: string;
filename: string;
version?: number;
}): Promise<Part | null>;
listArtifactKeys(args: {
appName: string;
userId: string;
sessionId: string;
}): Promise<string[]>;
deleteArtifact(args: {
appName: string;
userId: string;
sessionId: string;
filename: string;
}): Promise<void>;
listVersions(args: {
appName: string;
userId: string;
sessionId: string;
filename: string;
}): Promise<number[]>;
}
This consistent interface allows you to switch between implementations without changing your agent code.
InMemoryArtifactService
Fast, temporary storage for development and testing scenarios.
Characteristics
- Storage: Artifacts stored in memory only
- Persistence: Data lost when process terminates
- Performance: Fastest access, no network latency
- Scalability: Limited by available RAM
- Use Cases: Development, testing, prototyping
Setup and Configuration
import { InMemoryArtifactService, Runner } from '@iqai/adk';
// Create the service (no configuration needed)
const artifactService = new InMemoryArtifactService();
// Use with Runner
const runner = new Runner({
appName: "my_app",
agent: myAgent,
sessionService: mySessionService,
artifactService
});
Example Usage
import { InMemoryArtifactService } from '@iqai/adk';
const artifactService = new InMemoryArtifactService();
// Save an artifact
const textArtifact = {
inlineData: {
data: Buffer.from('Hello, World!').toString('base64'),
mimeType: 'text/plain'
}
};
const version = await artifactService.saveArtifact({
appName: 'test_app',
userId: 'user123',
sessionId: 'session456',
filename: 'greeting.txt',
artifact: textArtifact
});
console.log(`Saved version: ${version}`); // 0
// Load the artifact
const loaded = await artifactService.loadArtifact({
appName: 'test_app',
userId: 'user123',
sessionId: 'session456',
filename: 'greeting.txt'
});
if (loaded) {
const text = Buffer.from(loaded.inlineData.data, 'base64').toString();
console.log(`Loaded: ${text}`); // "Hello, World!"
}
Internal Implementation
The InMemoryArtifactService
uses a simple Map
to store artifacts:
// Internal storage structure
private readonly artifacts: Map<string, Part[]> = new Map();
// Path generation handles scoping
private getArtifactPath(
appName: string,
userId: string,
sessionId: string,
filename: string
): string {
if (filename.startsWith("user:")) {
return `${appName}/${userId}/user/${filename}`;
}
return `${appName}/${userId}/${sessionId}/${filename}`;
}
Data stored in InMemoryArtifactService
is lost when the process restarts. Use only for development and testing.
GcsArtifactService
Production-ready artifact storage using Google Cloud Storage.
Characteristics
- Storage: Google Cloud Storage buckets
- Persistence: Durable, replicated storage
- Performance: Network-dependent, highly optimized
- Scalability: Virtually unlimited
- Use Cases: Production deployments, large-scale applications
Setup and Configuration
import { GcsArtifactService, Runner } from '@iqai/adk';
// Basic configuration
const artifactService = new GcsArtifactService('my-artifacts-bucket');
// Use with Runner
const runner = new Runner({
appName: "production_app",
agent: myAgent,
sessionService: mySessionService,
artifactService
});
Google Cloud Setup
Before using GcsArtifactService
, ensure your Google Cloud environment is configured:
- Create a Storage Bucket:
gsutil mb gs://my-artifacts-bucket
- Set up Authentication:
# Using service account
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
# Or using gcloud CLI
gcloud auth application-default login
- Set Bucket Permissions:
# Grant your service account storage access
gsutil iam ch serviceAccount:my-service@project.iam.gserviceaccount.com:roles/storage.objectAdmin gs://my-artifacts-bucket
Storage Structure
The GCS implementation organizes artifacts using a hierarchical structure:
my-artifacts-bucket/
├── app1/
│ ├── user123/
│ │ ├── session456/
│ │ │ ├── temp_file.txt/
│ │ │ │ ├── 0 (version 0)
│ │ │ │ └── 1 (version 1)
│ │ │ └── analysis.json/
│ │ │ └── 0
│ │ └── user/
│ │ └── user:profile.png/
│ │ ├── 0
│ │ └── 1
│ └── user456/
│ └── ...
└── app2/
└── ...
Example Usage
import { GcsArtifactService } from '@iqai/adk';
const artifactService = new GcsArtifactService('my-artifacts-bucket');
// Save a large binary file
const imageData = Buffer.from(/* your image data */);
const imageArtifact = {
inlineData: {
data: imageData.toString('base64'),
mimeType: 'image/png'
}
};
try {
const version = await artifactService.saveArtifact({
appName: 'photo_app',
userId: 'user789',
sessionId: 'session123',
filename: 'user:profile_picture.png',
artifact: imageArtifact
});
console.log(`Image saved as version ${version}`);
// List all artifact filenames for this user/session
const artifactKeys = await artifactService.listArtifactKeys({
appName: 'photo_app',
userId: 'user789',
sessionId: 'session123'
});
console.log('Available artifacts:', artifactKeys);
// ['user:profile_picture.png', ...]
} catch (error) {
console.error('GCS operation failed:', error);
}
Performance Considerations
Optimization Strategies:
// Batch operations when possible
const operations = [
artifactService.saveArtifact({ /* args1 */ }),
artifactService.saveArtifact({ /* args2 */ }),
artifactService.saveArtifact({ /* args3 */ })
];
const versions = await Promise.all(operations);
console.log('All artifacts saved:', versions);
// Use streaming for large files
const loadLargeArtifact = async (filename: string) => {
try {
const artifact = await artifactService.loadArtifact({
appName: 'my_app',
userId: 'user123',
sessionId: 'session456',
filename
});
if (artifact && artifact.inlineData.data.length > 10 * 1024 * 1024) {
console.log('Large artifact detected, consider streaming');
}
return artifact;
} catch (error) {
console.error('Failed to load large artifact:', error);
return null;
}
};
Error Handling
const robustGcsOperations = async () => {
const artifactService = new GcsArtifactService('my-bucket');
try {
const artifact = await artifactService.loadArtifact({
appName: 'my_app',
userId: 'user123',
sessionId: 'session456',
filename: 'config.json'
});
if (!artifact) {
console.log('Artifact not found, creating default');
// Create and save default artifact
}
} catch (error) {
if (error.code === 404) {
console.log('Bucket or file not found');
} else if (error.code === 403) {
console.error('Permission denied - check IAM settings');
} else {
console.error('Unexpected GCS error:', error);
}
// Implement fallback behavior
return getDefaultConfig();
}
};
The GCS service automatically handles retries for transient errors and provides built-in redundancy and durability.
Custom Service Implementation
You can implement your own artifact service by extending the BaseArtifactService
interface for specific requirements like database storage or caching layers.
Service Selection Guide
Choose the appropriate artifact service based on your requirements:
Development and Testing
- Use:
InMemoryArtifactService
- Reasons: Fast, simple setup, no external dependencies
- Limitations: Data lost on restart
Production Applications
- Use:
GcsArtifactService
or custom database service - Reasons: Durable storage, scalability, backup/recovery
- Considerations: Network latency, cost, compliance requirements
Hybrid Scenarios
- Use: Combination approach with caching
- Implementation: Database/GCS for persistence + Redis for caching
- Benefits: Fast access with durability
Performance Comparison
Service Type | Read Speed | Write Speed | Durability | Scalability | Setup Complexity |
---|---|---|---|---|---|
InMemory | Fastest | Fastest | None | RAM-limited | Minimal |
GCS | Fast | Fast | High | Unlimited | Moderate |
Database | Moderate | Moderate | High | High | High |
Redis | Very Fast | Very Fast | Moderate | High | Moderate |
Choose based on your specific requirements for performance, durability, and operational complexity.