TypeScriptADK-TS

Service Implementations

Choose between in-memory and Google Cloud Storage artifact backends for your ADK-TS agents.

ADK-TS ships two artifact service implementations: InMemoryArtifactService for development and GcsArtifactService for production. Both implement the same BaseArtifactService interface, so switching between them requires no changes to your agent or tool code — only the service you pass to the Runner changes.

Choosing a service

ServicePersistenceUse forSetup
InMemoryArtifactServiceNoneDevelopment and testingZero config
GcsArtifactServiceDurableProductionGCS bucket
Custom implementationVariesPostgreSQL, S3, Redis, etc.You implement

InMemoryArtifactService loses all data when the process restarts. Never use it in production — switch to GcsArtifactService or a custom backend.

InMemoryArtifactService

Data lives in process memory with no configuration needed. It is the right choice for local development, unit tests, and examples — anywhere you don't need persistence.

import { AgentBuilder, InMemoryArtifactService } from "@iqai/adk";

const { runner } = await AgentBuilder.create("my_agent")
  .withModel("gemini-2.5-flash")
  .withArtifactService(new InMemoryArtifactService())
  .build();

You can also use the service directly — for example, in tests where you want to call the service API without a running agent:

import { InMemoryArtifactService } from "@iqai/adk";

const svc = new InMemoryArtifactService();

const version = await svc.saveArtifact({
  appName: "test_app",
  userId: "u1",
  sessionId: "s1",
  filename: "greeting.txt",
  artifact: { text: "Hello, World!" },
});
// version → 0

const loaded = await svc.loadArtifact({
  appName: "test_app",
  userId: "u1",
  sessionId: "s1",
  filename: "greeting.txt",
});
// loaded → { text: "Hello, World!" }

GcsArtifactService

Backed by a Google Cloud Storage bucket — durable, replicated, and with no practical storage limit. This is the service to use in production.

Before using it, you need a GCP project, a GCS bucket, and a service account with roles/storage.objectAdmin on that bucket.

By default, the service picks up credentials from Application Default Credentials (ADC). Run gcloud auth application-default login once locally, or set GOOGLE_APPLICATION_CREDENTIALS in production:

import { AgentBuilder, GcsArtifactService } from "@iqai/adk";

const { runner } = await AgentBuilder.create("my_agent")
  .withModel("gemini-2.5-flash")
  .withArtifactService(new GcsArtifactService("my-artifacts-bucket"))
  .build();

If you need to specify credentials explicitly — for example, to use a service account key file instead of ADC — pass them as the second argument:

import { GcsArtifactService } from "@iqai/adk";

const artifactService = new GcsArtifactService("my-artifacts-bucket", {
  projectId: "my-gcp-project",
  keyFilename: "/path/to/service-account.json",
});

Run these commands once to create your bucket and grant the service account access:

# Create the bucket
gsutil mb gs://my-artifacts-bucket

# Authenticate (choose one approach)
gcloud auth application-default login
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"

# Grant the service account storage access
gsutil iam ch serviceAccount:svc@project.iam.gserviceaccount.com:roles/storage.objectAdmin gs://my-artifacts-bucket

Storage layout

GCS stores each artifact version as a separate blob. Understanding the path structure helps when browsing your bucket or debugging missing files:

{appName}/{userId}/{sessionId}/{filename}/{version}   ← session-scoped
{appName}/{userId}/user/{filename}/{version}          ← user-scoped (user: prefix)

The user: prefix on a filename swaps the {sessionId} segment for user, which is why user-scoped artifacts are visible across all sessions.

Custom service

If you need a different backend — PostgreSQL, S3, Redis, or anything else — implement the BaseArtifactService interface. Your class only needs five methods:

import type { BaseArtifactService } from "@iqai/adk";
import type { Part } from "@google/genai";

class MyDatabaseArtifactService implements BaseArtifactService {
  async saveArtifact(args: {
    appName: string;
    userId: string;
    sessionId: string;
    filename: string;
    artifact: Part;
  }): Promise<number> {
    // Write the artifact to your database, return the new version number
    return 0;
  }

  async loadArtifact(args: {
    appName: string;
    userId: string;
    sessionId: string;
    filename: string;
    version?: number;
  }): Promise<Part | null> {
    // Return the artifact Part, or null if not found
    return null;
  }

  async listArtifactKeys(args: {
    appName: string;
    userId: string;
    sessionId: string;
  }): Promise<string[]> {
    // Return all filenames for this session
    return [];
  }

  async deleteArtifact(args: {
    appName: string;
    userId: string;
    sessionId: string;
    filename: string;
  }): Promise<void> {
    // Delete all versions of this filename
  }

  async listVersions(args: {
    appName: string;
    userId: string;
    sessionId: string;
    filename: string;
  }): Promise<number[]> {
    // Return all version numbers for this filename
    return [];
  }
}

Pass your custom service to the runner the same way as the built-in ones:

import { AgentBuilder } from "@iqai/adk";

const { runner } = await AgentBuilder.create("my_agent")
  .withModel("gemini-2.5-flash")
  .withArtifactService(new MyDatabaseArtifactService())
  .build();

Troubleshooting

IssueFix
"Artifact service is not initialized"Pass artifactService to Runner or use .withArtifactService() on AgentBuilder
GCS 403 ForbiddenService account needs roles/storage.objectAdmin on the bucket
GCS 404 Not Found on loadArtifact doesn't exist at that path or version — loadArtifact returns undefined
Data missing after restartInMemoryArtifactService doesn't persist — switch to GcsArtifactService for prod

Next steps