Change the ID strategy
In shortHow to control the format of thread IDs and run IDs generated by the framework using BaseIDGenerator.
- 2 min read
- 7 sections
- Updated
- v0.9.2
- Markdown
By default, 10xGraph 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 tenxgraph.core import StateGraph
from tenxgraph.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
| Class | id_type |
Example output | Use when |
|---|---|---|---|
DefaultIDGenerator |
STRING |
"" (falls back to framework UUID) |
Default - framework picks UUID if empty. |
UUIDGenerator |
STRING |
"550e8400-e29b-41d4-a716-446655440000" |
Maximum collision resistance; stateless. |
BigIntIDGenerator |
BIGINT |
1712576400000000000 |
PostgreSQL bigint primary keys; sortable by time. |
TimestampIDGenerator |
INTEGER |
1712576400123456 |
16-digit microsecond integer; sortable. |
IntIDGenerator |
INTEGER |
2147483647 |
32-bit random integer; small storage footprint. |
HexIDGenerator |
STRING |
"1a2b3c4d5e6f7890abcdef1234567890" |
32-char hex; no hyphens. |
ShortIDGenerator |
STRING |
"Ab3XyZ9k" |
Human-readable 8-char codes; URL-safe. |
All classes are importable from tenxgraph.utils.id_generator or the top-level tenxgraph.utils.
Write a custom generator
from tenxgraph.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 tenxgraph.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 stateCommon errors
| Error | Cause | Fix |
|---|---|---|
IDs collide in BigIntIDGenerator at very high throughput |
Two calls land in the same nanosecond. | Switch to UUIDGenerator or add a random suffix. |
IntIDGenerator causes UNIQUE constraint failures |
32-bit space is too small for your dataset. | Use BigIntIDGenerator or UUIDGenerator. |
ShortIDGenerator collisions in production |
62^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. |