Skip to main content

Change the ID strategy

By default, agentflow generates UUID v4 strings for thread IDs and run IDs. If your storage backend requires integer primary keys, short human-readable codes, or timestamp-sortable IDs, you can swap in a different generator.

Prerequisites

You have a working graph. No extra packages required.

Quick start: switch to timestamp-based integers

from agentflow.core import StateGraph
from agentflow.utils.id_generator import BigIntIDGenerator

graph = StateGraph(
id_generator=BigIntIDGenerator(),
)
app = graph.compile()

Every thread and run created by this graph will now have a 19-digit integer ID based on the current nanosecond timestamp.

Available generators

Classid_typeExample outputUse when
DefaultIDGeneratorSTRING"" (falls back to framework UUID)Default — framework picks UUID if empty.
UUIDGeneratorSTRING"550e8400-e29b-41d4-a716-446655440000"Maximum collision resistance; stateless.
BigIntIDGeneratorBIGINT1712576400000000000PostgreSQL bigint primary keys; sortable by time.
TimestampIDGeneratorINTEGER171257640012345616-digit microsecond integer; sortable.
IntIDGeneratorINTEGER214748364732-bit random integer; small storage footprint.
HexIDGeneratorSTRING"1a2b3c4d5e6f7890abcdef1234567890"32-char hex; no hyphens.
ShortIDGeneratorSTRING"Ab3XyZ9k"Human-readable 8-char codes; URL-safe.

All classes are importable from agentflow.utils.id_generator or the top-level agentflow.utils.

Write a custom generator

from agentflow.utils.id_generator import BaseIDGenerator, IDType
import uuid

class PrefixedUUIDGenerator(BaseIDGenerator):
"""Generates IDs like 'sess_550e8400-e29b-...' for easy prefix filtering."""

def __init__(self, prefix: str = "sess"):
self.prefix = prefix

@property
def id_type(self) -> IDType:
return IDType.STRING

def generate(self) -> str:
return f"{self.prefix}_{uuid.uuid4()}"


graph = StateGraph(id_generator=PrefixedUUIDGenerator("run"))

Async generators

If your ID generation requires I/O (for example, fetching a sequence from a database), implement AsyncIDGenerator:

from agentflow.utils.id_generator import AsyncIDGenerator, IDType

class DatabaseSequenceGenerator(AsyncIDGenerator):
"""Fetch the next integer sequence from PG."""

def __init__(self, pool):
self.pool = pool

@property
def id_type(self) -> IDType:
return IDType.BIGINT

async def generate(self) -> int:
async with self.pool.acquire() as conn:
return await conn.fetchval("SELECT nextval('agentflow_id_seq')")

Access the generated ID inside a node

The current run's generated ID is available via dependency injection:

from injectq import Inject

async def my_node(
state,
config: dict,
generated_id: str = Inject["generated_id"],
) -> ...:
print(f"This run ID: {generated_id}")
return state

Common errors

ErrorCauseFix
IDs collide in BigIntIDGenerator at very high throughputTwo calls land in the same nanosecond.Switch to UUIDGenerator or add a random suffix.
IntIDGenerator causes UNIQUE constraint failures32-bit space is too small for your dataset.Use BigIntIDGenerator or UUIDGenerator.
ShortIDGenerator collisions in production62^8 ≈ 218 trillion possibilities but not cryptographically guaranteed unique.Only use for low-volume, human-facing IDs; don't use as a DB primary key.