kurrent-agent-schema 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kurrent_agent_schema/__init__.py +78 -0
- kurrent_agent_schema/events.py +304 -0
- kurrent_agent_schema/streams.py +43 -0
- kurrent_agent_schema/usage.py +32 -0
- kurrent_agent_schema/version.py +9 -0
- kurrent_agent_schema-0.1.0.dist-info/METADATA +68 -0
- kurrent_agent_schema-0.1.0.dist-info/RECORD +8 -0
- kurrent_agent_schema-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Canonical event schema for Kurrent agent integrations.
|
|
2
|
+
|
|
3
|
+
See ``schema/SCHEMA_v2.md`` at the repo root for the prose specification.
|
|
4
|
+
This package is the Python mirror; ``Kurrent.Agent.Schema`` is the .NET mirror.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from kurrent_agent_schema.events import (
|
|
8
|
+
AgentConfig,
|
|
9
|
+
ArtifactVersionCreated,
|
|
10
|
+
AssistantTextGenerated,
|
|
11
|
+
AssistantThinkingGenerated,
|
|
12
|
+
AssistantToolCallsGenerated,
|
|
13
|
+
EvalRunCompleted,
|
|
14
|
+
EvalRunStarted,
|
|
15
|
+
FactRetained,
|
|
16
|
+
InterruptIssued,
|
|
17
|
+
InterruptResolved,
|
|
18
|
+
SessionContinuedAs,
|
|
19
|
+
SessionEnded,
|
|
20
|
+
SessionStarted,
|
|
21
|
+
SubagentCompleted,
|
|
22
|
+
SubagentStarted,
|
|
23
|
+
ToolCallInfo,
|
|
24
|
+
ToolResultReceived,
|
|
25
|
+
ToolSpec,
|
|
26
|
+
TurnScored,
|
|
27
|
+
UserMessageReceived,
|
|
28
|
+
)
|
|
29
|
+
from kurrent_agent_schema.streams import (
|
|
30
|
+
agent_artifact_stream,
|
|
31
|
+
agent_memory_stream,
|
|
32
|
+
agent_session_stream,
|
|
33
|
+
agent_subsession_stream,
|
|
34
|
+
eval_run_stream,
|
|
35
|
+
)
|
|
36
|
+
from kurrent_agent_schema.usage import TokenUsage, USAGE_METADATA_KEY
|
|
37
|
+
from kurrent_agent_schema.version import SCHEMA_VERSION
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
# Value types
|
|
41
|
+
"AgentConfig",
|
|
42
|
+
"ToolSpec",
|
|
43
|
+
"ToolCallInfo",
|
|
44
|
+
"TokenUsage",
|
|
45
|
+
# Session lifecycle
|
|
46
|
+
"SessionStarted",
|
|
47
|
+
"SessionEnded",
|
|
48
|
+
"SessionContinuedAs",
|
|
49
|
+
# Conversation
|
|
50
|
+
"UserMessageReceived",
|
|
51
|
+
"AssistantTextGenerated",
|
|
52
|
+
"AssistantToolCallsGenerated",
|
|
53
|
+
"AssistantThinkingGenerated",
|
|
54
|
+
"ToolResultReceived",
|
|
55
|
+
# Interrupts
|
|
56
|
+
"InterruptIssued",
|
|
57
|
+
"InterruptResolved",
|
|
58
|
+
# Subagents
|
|
59
|
+
"SubagentStarted",
|
|
60
|
+
"SubagentCompleted",
|
|
61
|
+
# Memory
|
|
62
|
+
"FactRetained",
|
|
63
|
+
# Artifacts
|
|
64
|
+
"ArtifactVersionCreated",
|
|
65
|
+
# Evaluation
|
|
66
|
+
"EvalRunStarted",
|
|
67
|
+
"TurnScored",
|
|
68
|
+
"EvalRunCompleted",
|
|
69
|
+
# Stream builders
|
|
70
|
+
"agent_session_stream",
|
|
71
|
+
"agent_subsession_stream",
|
|
72
|
+
"agent_memory_stream",
|
|
73
|
+
"agent_artifact_stream",
|
|
74
|
+
"eval_run_stream",
|
|
75
|
+
# Constants
|
|
76
|
+
"USAGE_METADATA_KEY",
|
|
77
|
+
"SCHEMA_VERSION",
|
|
78
|
+
]
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"""Canonical event models (schema v2).
|
|
2
|
+
|
|
3
|
+
See ``schema/SCHEMA_v2.md`` at the repo root for the prose specification.
|
|
4
|
+
|
|
5
|
+
All events inherit from ``_EventBase``, which carries the ``extensions``
|
|
6
|
+
envelope and the shared Pydantic configuration (``extra="ignore"`` for
|
|
7
|
+
forward-compatibility, frozen for hashability, snake_case JSON).
|
|
8
|
+
|
|
9
|
+
Stream placement and semantic conventions live in ``streams.py`` and the
|
|
10
|
+
schema doc — this module is strictly the type shapes.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
from pydantic import BaseModel, ConfigDict
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class _EventBase(BaseModel):
|
|
22
|
+
"""Shared configuration for every canonical event.
|
|
23
|
+
|
|
24
|
+
``extra="ignore"`` preserves forward-compatibility: unknown fields added
|
|
25
|
+
in a later minor version are dropped on read, not raised.
|
|
26
|
+
|
|
27
|
+
``ser_json_bytes="base64"`` / ``val_json_bytes="base64"`` round-trip
|
|
28
|
+
``bytes`` fields through JSON for ``ArtifactVersionCreated.inline_bytes``.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
model_config = ConfigDict(
|
|
32
|
+
populate_by_name=True,
|
|
33
|
+
extra="ignore",
|
|
34
|
+
frozen=True,
|
|
35
|
+
ser_json_bytes="base64",
|
|
36
|
+
val_json_bytes="base64",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
extensions: dict[str, dict[str, Any]] | None = None
|
|
40
|
+
"""Framework-specific extension envelope keyed by slug (``adk``, ``afw``,
|
|
41
|
+
``strands``, ``openai``, ``claude_sdk``, ``claude_code``, …).
|
|
42
|
+
See ``schema/SCHEMA_v2.md §5``."""
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# --- Value types -------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class ToolSpec(BaseModel):
|
|
49
|
+
"""Tool description captured in ``AgentConfig.tools``."""
|
|
50
|
+
|
|
51
|
+
model_config = ConfigDict(populate_by_name=True, extra="ignore", frozen=True)
|
|
52
|
+
|
|
53
|
+
name: str
|
|
54
|
+
description: str | None = None
|
|
55
|
+
input_schema: dict[str, Any] | None = None
|
|
56
|
+
source: str | None = None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class AgentConfig(BaseModel):
|
|
60
|
+
"""Informational snapshot of the agent configuration at session start.
|
|
61
|
+
|
|
62
|
+
All fields optional. Not a contract — readers use this for context, not
|
|
63
|
+
to reproduce the writer's agent.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
model_config = ConfigDict(populate_by_name=True, extra="ignore", frozen=True)
|
|
67
|
+
|
|
68
|
+
tools: list[ToolSpec] | None = None
|
|
69
|
+
plugins: list[str] | None = None
|
|
70
|
+
conversation_manager: dict[str, Any] | None = None
|
|
71
|
+
model_parameters: dict[str, Any] | None = None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class ToolCallInfo(BaseModel):
|
|
75
|
+
"""One tool call within ``AssistantToolCallsGenerated.tool_calls``."""
|
|
76
|
+
|
|
77
|
+
model_config = ConfigDict(populate_by_name=True, extra="ignore", frozen=True)
|
|
78
|
+
|
|
79
|
+
call_id: str
|
|
80
|
+
tool_name: str
|
|
81
|
+
arguments: dict[str, Any] | None = None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# --- Session lifecycle (SCHEMA_v2.md §3.1) -----------------------------------
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class SessionStarted(_EventBase):
|
|
88
|
+
app_name: str | None = None
|
|
89
|
+
agent_name: str | None = None
|
|
90
|
+
model: str | None = None
|
|
91
|
+
tenant_id: str | None = None
|
|
92
|
+
user_id: str | None = None
|
|
93
|
+
agent_config: AgentConfig | None = None
|
|
94
|
+
previous_session_id: str | None = None
|
|
95
|
+
"""Prior session this one resumes or forks from. New in v2."""
|
|
96
|
+
timestamp: datetime
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class SessionEnded(_EventBase):
|
|
100
|
+
reason: str | None = None
|
|
101
|
+
timestamp: datetime
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class SessionContinuedAs(_EventBase):
|
|
105
|
+
"""Written to the predecessor session pointing forward to its successor.
|
|
106
|
+
|
|
107
|
+
Paired with ``SessionStarted.previous_session_id`` on the successor, this
|
|
108
|
+
forms a bidirectional chain. New in v2.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
next_session_id: str
|
|
112
|
+
reason: str | None = None
|
|
113
|
+
timestamp: datetime
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# --- Conversation events (SCHEMA_v2.md §3.4) ---------------------------------
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class UserMessageReceived(_EventBase):
|
|
120
|
+
content: str | None = None
|
|
121
|
+
message_id: str | None = None
|
|
122
|
+
author_name: str | None = None
|
|
123
|
+
created_at: datetime | None = None
|
|
124
|
+
message_index: int
|
|
125
|
+
timestamp: datetime
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class AssistantTextGenerated(_EventBase):
|
|
129
|
+
content: str | None = None
|
|
130
|
+
message_id: str | None = None
|
|
131
|
+
author_name: str | None = None
|
|
132
|
+
created_at: datetime | None = None
|
|
133
|
+
message_index: int
|
|
134
|
+
timestamp: datetime
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class AssistantToolCallsGenerated(_EventBase):
|
|
138
|
+
tool_calls: list[ToolCallInfo]
|
|
139
|
+
content: str | None = None
|
|
140
|
+
message_id: str | None = None
|
|
141
|
+
author_name: str | None = None
|
|
142
|
+
created_at: datetime | None = None
|
|
143
|
+
message_index: int
|
|
144
|
+
timestamp: datetime
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class AssistantThinkingGenerated(_EventBase):
|
|
148
|
+
"""Assistant reasoning output (extended thinking / o-series / Gemini thinking).
|
|
149
|
+
|
|
150
|
+
Plaintext reasoning in ``content`` for Claude and Gemini; encrypted blobs
|
|
151
|
+
from OpenAI o-series have ``encrypted=True`` with the opaque value in
|
|
152
|
+
``extensions.openai.thinking.raw`` and the provider signature on
|
|
153
|
+
``signature``. New in v2 (SCHEMA_v2.md §3.2).
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
content: str | None = None
|
|
157
|
+
encrypted: bool = False
|
|
158
|
+
signature: str | None = None
|
|
159
|
+
message_id: str | None = None
|
|
160
|
+
author_name: str | None = None
|
|
161
|
+
created_at: datetime | None = None
|
|
162
|
+
message_index: int
|
|
163
|
+
timestamp: datetime
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class ToolResultReceived(_EventBase):
|
|
167
|
+
call_id: str
|
|
168
|
+
tool_name: str | None = None
|
|
169
|
+
result: str | None = None
|
|
170
|
+
message_id: str | None = None
|
|
171
|
+
author_name: str | None = None
|
|
172
|
+
created_at: datetime | None = None
|
|
173
|
+
message_index: int
|
|
174
|
+
timestamp: datetime
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
# --- Interrupts (SCHEMA_v2.md §3.3) ------------------------------------------
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class InterruptIssued(_EventBase):
|
|
181
|
+
"""Mid-turn human-in-the-loop pause (permission prompt, approval, input, auth).
|
|
182
|
+
|
|
183
|
+
``kind`` is an open string; the documented set is
|
|
184
|
+
``permission | approval | input | auth``, readers must tolerate unknowns.
|
|
185
|
+
Framework-specific details (tool_input, auth challenge) go in
|
|
186
|
+
``extensions.{framework}.interrupt``. New in v2.
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
request_id: str
|
|
190
|
+
kind: str
|
|
191
|
+
tool_name: str | None = None
|
|
192
|
+
prompt: str | None = None
|
|
193
|
+
timestamp: datetime
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class InterruptResolved(_EventBase):
|
|
197
|
+
"""Resolution of an ``InterruptIssued``, keyed by the same ``request_id``.
|
|
198
|
+
|
|
199
|
+
``outcome`` documented set: ``allow | allow_once | allow_always | deny |
|
|
200
|
+
cancel | answered | timeout``. Open string; readers tolerate unknowns.
|
|
201
|
+
New in v2.
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
request_id: str
|
|
205
|
+
outcome: str
|
|
206
|
+
response: str | None = None
|
|
207
|
+
timestamp: datetime
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
# --- Subagents (SCHEMA_v2.md §3.5) -------------------------------------------
|
|
211
|
+
# Written to the PARENT session stream to record subagent lifecycle; the
|
|
212
|
+
# subagent's own conversation lives in AgentSubsession-{parent}-{agent_id}.
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class SubagentStarted(_EventBase):
|
|
216
|
+
agent_id: str
|
|
217
|
+
agent_type: str | None = None
|
|
218
|
+
prompt: str | None = None
|
|
219
|
+
subsession_stream: str | None = None
|
|
220
|
+
timestamp: datetime
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class SubagentCompleted(_EventBase):
|
|
224
|
+
agent_id: str
|
|
225
|
+
outcome: str | None = None
|
|
226
|
+
summary: str | None = None
|
|
227
|
+
timestamp: datetime
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
# --- Memory (SCHEMA_v2.md §3.7) ----------------------------------------------
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
class FactRetained(_EventBase):
|
|
234
|
+
fact: str
|
|
235
|
+
retained_at: datetime
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# --- Artifacts (SCHEMA_v2.md §3.7) -------------------------------------------
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class ArtifactVersionCreated(_EventBase):
|
|
242
|
+
version: int
|
|
243
|
+
mime_type: str | None = None
|
|
244
|
+
inline_bytes: bytes | None = None
|
|
245
|
+
canonical_uri: str | None = None
|
|
246
|
+
custom_metadata: dict[str, Any] | None = None
|
|
247
|
+
created_at: datetime
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
# --- Evaluation (SCHEMA_v2.md §3.7) ------------------------------------------
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
class EvalRunStarted(_EventBase):
|
|
254
|
+
session_id: str
|
|
255
|
+
scorer: str
|
|
256
|
+
criteria: str
|
|
257
|
+
timestamp: datetime
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class TurnScored(_EventBase):
|
|
261
|
+
session_id: str
|
|
262
|
+
turn_index: int
|
|
263
|
+
input: str | None = None
|
|
264
|
+
output: str | None = None
|
|
265
|
+
score: float
|
|
266
|
+
score_label: str | None = None
|
|
267
|
+
reason: str | None = None
|
|
268
|
+
timestamp: datetime
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
class EvalRunCompleted(_EventBase):
|
|
272
|
+
session_id: str
|
|
273
|
+
turns_scored: int
|
|
274
|
+
average_score: float
|
|
275
|
+
total_cost: float | None = None
|
|
276
|
+
timestamp: datetime
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
# --- Event type name registry -------------------------------------------------
|
|
280
|
+
|
|
281
|
+
EVENT_TYPE_NAMES: dict[type[_EventBase], str] = {
|
|
282
|
+
SessionStarted: "SessionStarted",
|
|
283
|
+
SessionEnded: "SessionEnded",
|
|
284
|
+
SessionContinuedAs: "SessionContinuedAs",
|
|
285
|
+
UserMessageReceived: "UserMessageReceived",
|
|
286
|
+
AssistantTextGenerated: "AssistantTextGenerated",
|
|
287
|
+
AssistantToolCallsGenerated: "AssistantToolCallsGenerated",
|
|
288
|
+
AssistantThinkingGenerated: "AssistantThinkingGenerated",
|
|
289
|
+
ToolResultReceived: "ToolResultReceived",
|
|
290
|
+
InterruptIssued: "InterruptIssued",
|
|
291
|
+
InterruptResolved: "InterruptResolved",
|
|
292
|
+
SubagentStarted: "SubagentStarted",
|
|
293
|
+
SubagentCompleted: "SubagentCompleted",
|
|
294
|
+
FactRetained: "FactRetained",
|
|
295
|
+
ArtifactVersionCreated: "ArtifactVersionCreated",
|
|
296
|
+
EvalRunStarted: "EvalRunStarted",
|
|
297
|
+
TurnScored: "TurnScored",
|
|
298
|
+
EvalRunCompleted: "EvalRunCompleted",
|
|
299
|
+
}
|
|
300
|
+
"""Canonical event type name on the wire (KurrentDB ``event_type``)
|
|
301
|
+
for each model class. Integration writers use this to stamp events;
|
|
302
|
+
readers use the inverse lookup."""
|
|
303
|
+
|
|
304
|
+
EVENT_TYPE_BY_NAME: dict[str, type[_EventBase]] = {v: k for k, v in EVENT_TYPE_NAMES.items()}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Canonical stream-name builders.
|
|
2
|
+
|
|
3
|
+
See ``schema/SCHEMA_v2.md §2`` for the full stream taxonomy.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
AGENT_SESSION_PREFIX: str = "AgentSession-"
|
|
9
|
+
AGENT_SUBSESSION_PREFIX: str = "AgentSubsession-"
|
|
10
|
+
AGENT_MEMORY_PREFIX: str = "AgentMemory-"
|
|
11
|
+
AGENT_ARTIFACT_PREFIX: str = "AgentArtifact-"
|
|
12
|
+
EVAL_RUN_PREFIX: str = "EvalRun-"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def agent_session_stream(session_id: str) -> str:
|
|
16
|
+
"""Primary conversation stream for a session."""
|
|
17
|
+
return f"{AGENT_SESSION_PREFIX}{session_id}"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def agent_subsession_stream(parent_session_id: str, agent_id: str) -> str:
|
|
21
|
+
"""Subagent conversation stream, scoped under a parent session.
|
|
22
|
+
|
|
23
|
+
See ``schema/SCHEMA_v2.md §3.5``.
|
|
24
|
+
"""
|
|
25
|
+
return f"{AGENT_SUBSESSION_PREFIX}{parent_session_id}-{agent_id}"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def agent_memory_stream(app_name: str, user_id: str) -> str:
|
|
29
|
+
"""Per-app, per-user retained facts. v1 default scope.
|
|
30
|
+
|
|
31
|
+
See ``schema/SCHEMA_v2.md §3.7`` (inherited from v1 §3.6).
|
|
32
|
+
"""
|
|
33
|
+
return f"{AGENT_MEMORY_PREFIX}{app_name}-{user_id}"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def agent_artifact_stream(scope: str, filename: str) -> str:
|
|
37
|
+
"""Binary artifact versions. ``scope`` is integration-defined."""
|
|
38
|
+
return f"{AGENT_ARTIFACT_PREFIX}{scope}-{filename}"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def eval_run_stream(run_id: str) -> str:
|
|
42
|
+
"""Eval run events."""
|
|
43
|
+
return f"{EVAL_RUN_PREFIX}{run_id}"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Token usage metadata model.
|
|
2
|
+
|
|
3
|
+
Usage rides on KurrentDB event metadata under the ``$usage`` key, on every
|
|
4
|
+
assistant event (``AssistantTextGenerated``, ``AssistantToolCallsGenerated``,
|
|
5
|
+
``AssistantThinkingGenerated``). It is *not* a canonical event payload.
|
|
6
|
+
|
|
7
|
+
See ``schema/SCHEMA_v2.md §3.6``.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from pydantic import BaseModel, ConfigDict
|
|
13
|
+
|
|
14
|
+
USAGE_METADATA_KEY: str = "$usage"
|
|
15
|
+
"""KurrentDB metadata key under which ``TokenUsage`` is written."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class TokenUsage(BaseModel):
|
|
19
|
+
"""Token counts reported by the model provider for one assistant event.
|
|
20
|
+
|
|
21
|
+
All fields optional — providers differ in which counts they return.
|
|
22
|
+
For ``AssistantThinkingGenerated``, populate ``reasoning_tokens``.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
model_config = ConfigDict(populate_by_name=True, extra="ignore", frozen=True)
|
|
26
|
+
|
|
27
|
+
input_tokens: int | None = None
|
|
28
|
+
output_tokens: int | None = None
|
|
29
|
+
total_tokens: int | None = None
|
|
30
|
+
cached_input_tokens: int | None = None
|
|
31
|
+
reasoning_tokens: int | None = None
|
|
32
|
+
model: str | None = None
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Schema version constant.
|
|
2
|
+
|
|
3
|
+
Stamped on event metadata under ``$schema_version``. Writers set this to
|
|
4
|
+
``SCHEMA_VERSION``; readers that encounter a higher version should either
|
|
5
|
+
reject the event or degrade gracefully via ``extra="ignore"`` semantics.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
SCHEMA_VERSION: int = 2
|
|
9
|
+
"""Kurrent agent event schema version. See ``schema/SCHEMA_v2.md``."""
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kurrent-agent-schema
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Canonical event schema for Kurrent agent integrations (schema v2)
|
|
5
|
+
Author: Kurrent, Inc.
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Keywords: agents,eventsourcing,kurrentdb,llm,schema
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Requires-Dist: pydantic>=2.5
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
12
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# kurrent-agent-schema
|
|
16
|
+
|
|
17
|
+
Canonical event schema types for Kurrent agent integrations — schema version **2**.
|
|
18
|
+
|
|
19
|
+
This package is the Python mirror of the canonical agent event schema shared across Kurrent's agent-framework integrations (Google ADK, Microsoft Agent Framework, Strands, OpenAI Agents, Claude Agent SDK) and Capacitor. The prose specification lives in [`schema/SCHEMA_v2.md`](../SCHEMA_v2.md); the .NET mirror is [`Kurrent.Agent.Schema`](../dotnet/Kurrent.Agent.Schema/).
|
|
20
|
+
|
|
21
|
+
## What's here
|
|
22
|
+
|
|
23
|
+
- **Canonical event models** (Pydantic v2): `SessionStarted`, `SessionEnded`, `SessionContinuedAs`, `UserMessageReceived`, `AssistantTextGenerated`, `AssistantToolCallsGenerated`, `AssistantThinkingGenerated`, `ToolResultReceived`, `InterruptIssued`, `InterruptResolved`, `SubagentStarted`, `SubagentCompleted`, `FactRetained`, `ArtifactVersionCreated`, `EvalRunStarted`, `TurnScored`, `EvalRunCompleted`.
|
|
24
|
+
- **Value types**: `AgentConfig`, `ToolSpec`, `ToolCallInfo`.
|
|
25
|
+
- **Usage metadata**: `TokenUsage` (carried on KurrentDB event metadata under the `$usage` key, not as a standalone event).
|
|
26
|
+
- **Stream-name builders**: `agent_session_stream`, `agent_subsession_stream`, `agent_memory_stream`, `agent_artifact_stream`, `eval_run_stream`.
|
|
27
|
+
- **Type-name registry**: `EVENT_TYPE_NAMES` / `EVENT_TYPE_BY_NAME` for wiring up KurrentDB event-type to/from CLR-type conversion.
|
|
28
|
+
|
|
29
|
+
## What's not here
|
|
30
|
+
|
|
31
|
+
- **Framework-specific events and extension shapes.** ADK's `AgentTransferred`/`Rewind`, AFW's workflow checkpoints, Capacitor's `AgentRunStarted`/visibility events, coding-agent fields under `extensions.claude_code.*`, etc. Those live in their owning integration packages — this package deliberately carries only the portable vocabulary.
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from datetime import datetime, timezone
|
|
37
|
+
from kurrent_agent_schema import (
|
|
38
|
+
SessionStarted, UserMessageReceived, AssistantTextGenerated,
|
|
39
|
+
TokenUsage, USAGE_METADATA_KEY, agent_session_stream,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
stream = agent_session_stream("sess-0001") # "AgentSession-sess-0001"
|
|
43
|
+
|
|
44
|
+
event = UserMessageReceived(
|
|
45
|
+
content="hello",
|
|
46
|
+
message_index=0,
|
|
47
|
+
timestamp=datetime.now(tz=timezone.utc),
|
|
48
|
+
extensions={"adk": {"invocation_id": "inv_abc"}},
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# $usage goes on KurrentDB metadata, not the payload
|
|
52
|
+
usage = TokenUsage(input_tokens=1507, output_tokens=203, model="claude-sonnet-4-6")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Drift guard
|
|
56
|
+
|
|
57
|
+
Every canonical event has a JSON fixture under [`schema/fixtures/events/`](../fixtures/events/). The test suite here runs a round-trip assertion per fixture; an equivalent suite in the .NET package runs against the same fixtures. Adding or modifying a canonical field requires a coordinated PR: update the model **and** the fixture, in both Python and .NET packages. CI fails otherwise.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cd schema/python
|
|
61
|
+
uv pip install -e ".[dev]"
|
|
62
|
+
pytest
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Version
|
|
66
|
+
|
|
67
|
+
- Package: `0.1.0` (initial pre-1.0 release carrying schema v2).
|
|
68
|
+
- Schema: `SCHEMA_VERSION = 2`, stamped on KurrentDB metadata under `$schema_version` by integration writers.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
kurrent_agent_schema/__init__.py,sha256=jPsSBDr8T74aR9bLH8NMcZ5W_3q6WJbbvphPyiEdMOk,1888
|
|
2
|
+
kurrent_agent_schema/events.py,sha256=Co_5lGNoJ90QY6WQHqnRpfezLJf8sKRoOmthxq8CLGg,8949
|
|
3
|
+
kurrent_agent_schema/streams.py,sha256=MEsLd4XdcxHOXi7VM-o4LV-BzWZId8671iDj3-VQWN0,1323
|
|
4
|
+
kurrent_agent_schema/usage.py,sha256=QNJlH_65j3LdsEQeks6q7O292FhKtKZ2AVptVqlTEiM,1047
|
|
5
|
+
kurrent_agent_schema/version.py,sha256=qcn69p4vcDIlm3IMouUYhBhxLY7AqyQiEyy-hk5_upo,349
|
|
6
|
+
kurrent_agent_schema-0.1.0.dist-info/METADATA,sha256=IiBDcdPLGrJQbtP2qjP4ZR4oGOk4D507gVaddSkKELM,3426
|
|
7
|
+
kurrent_agent_schema-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
8
|
+
kurrent_agent_schema-0.1.0.dist-info/RECORD,,
|