Cortex

Identity (TypeID)

How Cortex uses type-safe, prefix-qualified identifiers for every entity.

Every entity in Cortex gets a type-prefixed, K-sortable, UUIDv7-based identifier using the TypeID specification. IDs are validated at parse time to ensure the prefix matches the expected type.

Prefix table

TypePrefixGo typeExample
Agentagt_id.AgentIDagt_01h2xcejqtf2nbrexx3vqjhp41
Agent Runarun_id.AgentRunIDarun_01h2xcejqtf2nbrexx3vqjhp41
Tooltool_id.ToolIDtool_01h2xcejqtf2nbrexx3vqjhp41
Tool Calltcall_id.ToolCallIDtcall_01h2xcejqtf2nbrexx3vqjhp41
Stepastp_id.StepIDastp_01h2xcejqtf2nbrexx3vqjhp41
Memorymem_id.MemoryIDmem_01h2xcejqtf2nbrexx3vqjhp41
Checkpointacp_id.CheckpointIDacp_01h2xcejqtf2nbrexx3vqjhp41
Orchestrationorch_id.OrchestrationIDorch_01h2xcejqtf2nbrexx3vqjhp41
Skillskl_id.SkillIDskl_01h455vb4pex5vsknk084sn02q
Traittrt_id.TraitIDtrt_01h455vb4pex5vsknk084sn02q
Behaviorbhv_id.BehaviorIDbhv_01h455vb4pex5vsknk084sn02q
Personaprs_id.PersonaIDprs_01h455vb4pex5vsknk084sn02q

Constructors

Each type has a constructor that generates a new UUIDv7-based ID with the correct prefix:

import "github.com/xraph/cortex/id"

agentID  := id.NewAgentID()     // agt_01h...
runID    := id.NewAgentRunID()  // arun_01h...
skillID  := id.NewSkillID()    // skl_01h...
traitID  := id.NewTraitID()    // trt_01h...
personaID := id.NewPersonaID() // prs_01h...

Parsing

Parse functions validate both the format and the prefix:

agentID, err := id.ParseAgentID("agt_01h2xcejqtf2nbrexx3vqjhp41")
// err is nil — prefix matches

_, err = id.ParseAgentID("skl_01h455vb4pex5vsknk084sn02q")
// err: id: expected prefix "agt", got "skl"

Use id.ParseAny when you need to accept any valid TypeID regardless of prefix:

anyID, err := id.ParseAny("skl_01h455vb4pex5vsknk084sn02q")
// anyID.Prefix() == "skl"

K-sortability

TypeIDs embed UUIDv7 timestamps, making them naturally sortable by creation time. This means:

  • Database indexes on TypeID columns are efficient for time-range queries
  • IDs created later always sort after earlier IDs
  • No need for separate created_at indexes for ordering

Type safety

All ID types are aliases for typeid.TypeID. While Go does not enforce alias-level type safety at compile time, the prefix validation at parse time catches mismatches:

type AgentID = typeid.TypeID
type SkillID = typeid.TypeID

Passing a skill ID where an agent ID is expected will succeed at compile time but fail at parse time if the prefix is validated.

On this page