coreason-manifest 0.9.0__py3-none-any.whl → 0.12.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.
- coreason_manifest/__init__.py +47 -13
- coreason_manifest/common.py +64 -0
- coreason_manifest/governance.py +83 -0
- coreason_manifest/schemas/__init__.py +9 -1
- coreason_manifest/schemas/coreason-v2.schema.json +462 -0
- coreason_manifest/utils/__init__.py +10 -0
- coreason_manifest/utils/logger.py +10 -0
- coreason_manifest/v2/__init__.py +1 -0
- coreason_manifest/v2/governance.py +144 -0
- coreason_manifest/v2/io.py +132 -0
- coreason_manifest/v2/resolver.py +67 -0
- coreason_manifest/v2/spec/__init__.py +1 -0
- coreason_manifest/v2/spec/contracts.py +34 -0
- coreason_manifest/v2/spec/definitions.py +196 -0
- coreason_manifest/v2/validator.py +48 -0
- {coreason_manifest-0.9.0.dist-info → coreason_manifest-0.12.0.dist-info}/METADATA +68 -29
- coreason_manifest-0.12.0.dist-info/RECORD +20 -0
- {coreason_manifest-0.9.0.dist-info → coreason_manifest-0.12.0.dist-info}/WHEEL +1 -1
- coreason_manifest/definitions/__init__.py +0 -49
- coreason_manifest/definitions/agent.py +0 -292
- coreason_manifest/definitions/audit.py +0 -122
- coreason_manifest/definitions/events.py +0 -392
- coreason_manifest/definitions/message.py +0 -126
- coreason_manifest/definitions/simulation.py +0 -50
- coreason_manifest/definitions/topology.py +0 -255
- coreason_manifest/recipes.py +0 -76
- coreason_manifest/schemas/agent.schema.json +0 -849
- coreason_manifest-0.9.0.dist-info/RECORD +0 -18
- {coreason_manifest-0.9.0.dist-info → coreason_manifest-0.12.0.dist-info}/licenses/LICENSE +0 -0
- {coreason_manifest-0.9.0.dist-info → coreason_manifest-0.12.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coreason_manifest
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.0
|
|
4
4
|
Summary: This package is the definitive source of truth. If it isn't in the manifest, it doesn't exist. If it violates the manifest, it doesn't run.
|
|
5
5
|
License: # The Prosperity Public License 3.0.0
|
|
6
6
|
|
|
@@ -68,6 +68,7 @@ Classifier: License :: Other/Proprietary License
|
|
|
68
68
|
Classifier: Programming Language :: Python :: 3.12
|
|
69
69
|
Classifier: Operating System :: OS Independent
|
|
70
70
|
Requires-Dist: coreason-identity (>=0.4.1,<0.5.0)
|
|
71
|
+
Requires-Dist: jsonschema (>=4.19.0,<5.0.0)
|
|
71
72
|
Requires-Dist: loguru (>=0.7.2,<0.8.0)
|
|
72
73
|
Requires-Dist: pydantic (>=2.12.5,<3.0.0)
|
|
73
74
|
Requires-Dist: pyyaml (>=6.0.3,<7.0.0)
|
|
@@ -87,17 +88,25 @@ The definitive source of truth for CoReason-AI Asset definitions. "The Blueprint
|
|
|
87
88
|
|
|
88
89
|
## Overview
|
|
89
90
|
|
|
90
|
-
`coreason-manifest`
|
|
91
|
+
`coreason-manifest` serves as the **Shared Kernel** for the Coreason ecosystem. It contains the canonical Pydantic definitions, schemas, and data structures for Agents and Workflows (Recipes).
|
|
92
|
+
|
|
93
|
+
It provides the **"Blueprint"** that all other services (Builder, Engine, Simulator) rely on. It focuses on strict typing, schema validation, and serialization, ensuring that if it isn't in the manifest, it doesn't exist.
|
|
94
|
+
|
|
95
|
+
### Standards Clarification
|
|
96
|
+
*Note: The "Coreason Agent Manifest" (CAM) is a proprietary, strict governance schema designed for the CoReason Platform. It is distinct from the Oracle/Linux Foundation "Open Agent Specification," though we aim for future interoperability via adapters.*
|
|
91
97
|
|
|
92
98
|
## Features
|
|
93
99
|
|
|
94
|
-
* **
|
|
95
|
-
* **
|
|
96
|
-
* **
|
|
97
|
-
* **
|
|
98
|
-
* **
|
|
99
|
-
* **
|
|
100
|
-
|
|
100
|
+
* **Coreason Agent Manifest (CAM):** Strict Pydantic models for Agent definitions (`AgentDefinition`) and Recipes (`Recipe`).
|
|
101
|
+
* **Strict Typing:** Enforces type safety for critical interfaces.
|
|
102
|
+
* **Governance & Policy:** Enforce organizational rules (domains, risk levels) on agents via `GovernanceConfig`.
|
|
103
|
+
* **Ergonomic Factory Methods:** Simplified construction of manifests.
|
|
104
|
+
* **Flexible Tooling:** Support for external tool definitions (`ToolDefinition`) and risk levels (`ToolRiskLevel`).
|
|
105
|
+
* **Topology Visualization:** Workflows are defined as graph topologies (`Workflow`).
|
|
106
|
+
|
|
107
|
+
## Serialization & Base Model
|
|
108
|
+
|
|
109
|
+
Core definitions (e.g., `Manifest`, `Workflow`, `AgentDefinition`) inherit from Pydantic's `BaseModel`. Shared configuration models like `GovernanceConfig` inherit from `CoReasonBaseModel` for enhanced serialization capabilities.
|
|
101
110
|
|
|
102
111
|
## Installation
|
|
103
112
|
|
|
@@ -107,30 +116,60 @@ pip install coreason-manifest
|
|
|
107
116
|
|
|
108
117
|
## Usage
|
|
109
118
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
### 1. Library Usage
|
|
113
|
-
|
|
114
|
-
Use the python library to validate local agent files and verify source integrity.
|
|
119
|
+
This library is used to define and validate Agent configurations programmatically.
|
|
115
120
|
|
|
116
121
|
```python
|
|
117
|
-
from coreason_manifest import
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
122
|
+
from coreason_manifest import (
|
|
123
|
+
Recipe,
|
|
124
|
+
ManifestMetadata,
|
|
125
|
+
AgentStep,
|
|
126
|
+
Workflow,
|
|
127
|
+
InterfaceDefinition,
|
|
128
|
+
StateDefinition,
|
|
129
|
+
PolicyDefinition
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# 1. Define Metadata
|
|
133
|
+
metadata = ManifestMetadata(
|
|
134
|
+
name="Research Agent",
|
|
135
|
+
version="1.0.0"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# 2. Define Workflow
|
|
139
|
+
workflow = Workflow(
|
|
140
|
+
start="step1",
|
|
141
|
+
steps={
|
|
142
|
+
"step1": AgentStep(
|
|
143
|
+
id="step1",
|
|
144
|
+
agent="gpt-4-researcher",
|
|
145
|
+
next="step2"
|
|
146
|
+
),
|
|
147
|
+
# ... define other steps
|
|
148
|
+
}
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# 3. Instantiate Manifest
|
|
152
|
+
manifest = Recipe(
|
|
153
|
+
apiVersion="coreason.ai/v2",
|
|
154
|
+
kind="Recipe",
|
|
155
|
+
metadata=metadata,
|
|
156
|
+
interface=InterfaceDefinition(
|
|
157
|
+
inputs={"topic": {"type": "string"}},
|
|
158
|
+
outputs={"summary": {"type": "string"}}
|
|
159
|
+
),
|
|
160
|
+
state=StateDefinition(),
|
|
161
|
+
policy=PolicyDefinition(max_retries=3),
|
|
162
|
+
workflow=workflow
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
print(f"Manifest '{manifest.metadata.name}' created successfully.")
|
|
131
166
|
```
|
|
132
167
|
|
|
133
168
|
For full details, see the [Usage Documentation](docs/usage.md).
|
|
134
169
|
|
|
135
|
-
|
|
170
|
+
## Documentation
|
|
171
|
+
|
|
172
|
+
* [Usage Guide](docs/usage.md): How to load and create manifests.
|
|
173
|
+
* [Governance & Policy Enforcement](docs/governance_policy_enforcement.md): Validating agents against organizational rules.
|
|
174
|
+
* [Coreason Agent Manifest (CAM)](docs/cap/specification.md): The Canonical YAML Authoring Format.
|
|
136
175
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
coreason_manifest/__init__.py,sha256=W74fAYQGapYpNq117NHIUeQvFddn22lJ4IxtMiVBtuE,1189
|
|
2
|
+
coreason_manifest/common.py,sha256=ebQPiWiYSKFVAS6eXUyOIgJbsO8QDXVlFQKtSCQLRzg,2136
|
|
3
|
+
coreason_manifest/governance.py,sha256=cR0q3TUbwTx2-ROGtVh9tP6o9XUiD2ekqoNsgCPDR2o,3299
|
|
4
|
+
coreason_manifest/schemas/__init__.py,sha256=g1cCu1DprGcnGAiuvYWz5VeKKXIHYYwlrsqdkg9fRZY,412
|
|
5
|
+
coreason_manifest/schemas/coreason-v2.schema.json,sha256=R2UqXEY1NSpNNtGpyJnjJ0jhnT4U6-2FKn-WPi4tnD0,11312
|
|
6
|
+
coreason_manifest/utils/__init__.py,sha256=Kdz519fMq6c7Px3MP5oD_9jfqqFbCiaHPBQTc0LhyII,848
|
|
7
|
+
coreason_manifest/utils/logger.py,sha256=dwvFVR2CuOjKsE0_59JsGqoIh8GpAwO6ATJDFt2SOlg,1640
|
|
8
|
+
coreason_manifest/v2/__init__.py,sha256=1bWTcGLOXjSDv2TgYXoH5wsla0T2W2ulhUHsK5AzIgM,23
|
|
9
|
+
coreason_manifest/v2/governance.py,sha256=nN2eu2YeASuDQglb35IOYm525LXWovMzAt9mba8loTY,5929
|
|
10
|
+
coreason_manifest/v2/io.py,sha256=6B5wzyW-TbnKcUgOOBaurSdZg0kQPtPx35hlcsbe1Us,4311
|
|
11
|
+
coreason_manifest/v2/resolver.py,sha256=lLPbNZcQjQ_GI71a7Rf-XiMM0CDgTy96nTLxm94gJLg,2313
|
|
12
|
+
coreason_manifest/v2/spec/__init__.py,sha256=i8Agxsn9vs6wGCaxaHVNupRpPCeAIGTtiA9FKyoJsaU,40
|
|
13
|
+
coreason_manifest/v2/spec/contracts.py,sha256=bDlYHDWlpSsIzDU8_fwXS2d0NjEHAPkIK3VpJbvcL7k,1354
|
|
14
|
+
coreason_manifest/v2/spec/definitions.py,sha256=TV2JHBBq90jN18xg5sG9Y_swd1blcXyomLb1H6DkpW4,8603
|
|
15
|
+
coreason_manifest/v2/validator.py,sha256=iTkpb_V38KbJ89h-Zne_1xep-XL44PS1PobZRnwV5K8,1504
|
|
16
|
+
coreason_manifest-0.12.0.dist-info/METADATA,sha256=R9MkpePi9F8sGa14-aNahaerSNOvZcFaAeiGVKcDZHg,8278
|
|
17
|
+
coreason_manifest-0.12.0.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
|
|
18
|
+
coreason_manifest-0.12.0.dist-info/licenses/LICENSE,sha256=3tYb7ZQe7sVXcbNmX22fDESFjOSIlCZodUGpZMkuSlk,3063
|
|
19
|
+
coreason_manifest-0.12.0.dist-info/licenses/NOTICE,sha256=tqzUyP9VTCGxoHLgBI0AC1i0G7m_PSyESFL8Jwuw0dA,610
|
|
20
|
+
coreason_manifest-0.12.0.dist-info/RECORD,,
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
from .agent import AgentDefinition, AgentRuntimeConfig
|
|
2
|
-
from .events import (
|
|
3
|
-
ArtifactGenerated,
|
|
4
|
-
ArtifactGeneratedPayload,
|
|
5
|
-
CouncilVote,
|
|
6
|
-
CouncilVotePayload,
|
|
7
|
-
EdgeTraversed,
|
|
8
|
-
EdgeTraversedPayload,
|
|
9
|
-
GraphEvent,
|
|
10
|
-
NodeCompleted,
|
|
11
|
-
NodeCompletedPayload,
|
|
12
|
-
NodeInit,
|
|
13
|
-
# Export Aliases too
|
|
14
|
-
NodeInitPayload,
|
|
15
|
-
NodeRestored,
|
|
16
|
-
NodeSkipped,
|
|
17
|
-
NodeSkippedPayload,
|
|
18
|
-
NodeStarted,
|
|
19
|
-
NodeStartedPayload,
|
|
20
|
-
NodeStream,
|
|
21
|
-
NodeStreamPayload,
|
|
22
|
-
WorkflowError,
|
|
23
|
-
WorkflowErrorPayload,
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
__all__ = [
|
|
27
|
-
"AgentRuntimeConfig",
|
|
28
|
-
"AgentDefinition",
|
|
29
|
-
"GraphEvent",
|
|
30
|
-
"NodeInit",
|
|
31
|
-
"NodeStarted",
|
|
32
|
-
"NodeCompleted",
|
|
33
|
-
"NodeRestored",
|
|
34
|
-
"NodeSkipped",
|
|
35
|
-
"NodeStream",
|
|
36
|
-
"ArtifactGenerated",
|
|
37
|
-
"EdgeTraversed",
|
|
38
|
-
"CouncilVote",
|
|
39
|
-
"WorkflowError",
|
|
40
|
-
"NodeInitPayload",
|
|
41
|
-
"NodeStartedPayload",
|
|
42
|
-
"NodeCompletedPayload",
|
|
43
|
-
"NodeSkippedPayload",
|
|
44
|
-
"NodeStreamPayload",
|
|
45
|
-
"EdgeTraversedPayload",
|
|
46
|
-
"ArtifactGeneratedPayload",
|
|
47
|
-
"CouncilVotePayload",
|
|
48
|
-
"WorkflowErrorPayload",
|
|
49
|
-
]
|
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
# Prosperity-3.0
|
|
2
|
-
"""Pydantic models for the Coreason Manifest system.
|
|
3
|
-
|
|
4
|
-
These models define the structure and validation rules for the Agent Manifest
|
|
5
|
-
(OAS). They represent the source of truth for Agent definitions.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
from datetime import datetime
|
|
11
|
-
from enum import Enum
|
|
12
|
-
from types import MappingProxyType
|
|
13
|
-
from typing import Any, Dict, List, Mapping, Optional, Tuple
|
|
14
|
-
from uuid import UUID
|
|
15
|
-
|
|
16
|
-
from pydantic import (
|
|
17
|
-
AfterValidator,
|
|
18
|
-
AnyUrl,
|
|
19
|
-
BaseModel,
|
|
20
|
-
ConfigDict,
|
|
21
|
-
Field,
|
|
22
|
-
PlainSerializer,
|
|
23
|
-
field_validator,
|
|
24
|
-
model_validator,
|
|
25
|
-
)
|
|
26
|
-
from typing_extensions import Annotated
|
|
27
|
-
|
|
28
|
-
from coreason_manifest.definitions.topology import Edge, Node
|
|
29
|
-
|
|
30
|
-
# SemVer Regex pattern (simplified for standard SemVer)
|
|
31
|
-
# Modified to accept optional 'v' or 'V' prefix (multiple allowed) for input normalization
|
|
32
|
-
SEMVER_REGEX = (
|
|
33
|
-
r"^[vV]*(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)"
|
|
34
|
-
r"(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?"
|
|
35
|
-
r"(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def normalize_version(v: str) -> str:
|
|
40
|
-
"""Normalize version string by recursively stripping 'v' or 'V' prefix.
|
|
41
|
-
|
|
42
|
-
Args:
|
|
43
|
-
v: The version string to normalize.
|
|
44
|
-
|
|
45
|
-
Returns:
|
|
46
|
-
The normalized version string without 'v' prefix.
|
|
47
|
-
"""
|
|
48
|
-
while v.lower().startswith("v"):
|
|
49
|
-
v = v[1:]
|
|
50
|
-
return v
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
# Annotated type that validates SemVer regex (allowing multiple v) then normalizes to strict SemVer (no v)
|
|
54
|
-
VersionStr = Annotated[
|
|
55
|
-
str,
|
|
56
|
-
Field(pattern=SEMVER_REGEX),
|
|
57
|
-
AfterValidator(normalize_version),
|
|
58
|
-
]
|
|
59
|
-
|
|
60
|
-
# Reusable immutable dictionary type
|
|
61
|
-
ImmutableDict = Annotated[
|
|
62
|
-
Mapping[str, Any],
|
|
63
|
-
AfterValidator(lambda x: MappingProxyType(x)),
|
|
64
|
-
PlainSerializer(lambda x: dict(x), return_type=Dict[str, Any]),
|
|
65
|
-
]
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
# Strict URI type that serializes to string
|
|
69
|
-
StrictUri = Annotated[
|
|
70
|
-
AnyUrl,
|
|
71
|
-
PlainSerializer(lambda x: str(x), return_type=str),
|
|
72
|
-
]
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
class AgentMetadata(BaseModel):
|
|
76
|
-
"""Metadata for the Agent.
|
|
77
|
-
|
|
78
|
-
Attributes:
|
|
79
|
-
id: Unique Identifier for the Agent (UUID).
|
|
80
|
-
version: Semantic Version of the Agent.
|
|
81
|
-
name: Name of the Agent.
|
|
82
|
-
author: Author of the Agent.
|
|
83
|
-
created_at: Creation timestamp (ISO 8601).
|
|
84
|
-
"""
|
|
85
|
-
|
|
86
|
-
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
87
|
-
|
|
88
|
-
id: UUID = Field(..., description="Unique Identifier for the Agent (UUID).")
|
|
89
|
-
version: VersionStr = Field(..., description="Semantic Version of the Agent.")
|
|
90
|
-
name: str = Field(..., min_length=1, description="Name of the Agent.")
|
|
91
|
-
author: str = Field(..., min_length=1, description="Author of the Agent.")
|
|
92
|
-
created_at: datetime = Field(..., description="Creation timestamp (ISO 8601).")
|
|
93
|
-
requires_auth: bool = Field(default=False, description="Whether the agent requires user authentication.")
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class AgentInterface(BaseModel):
|
|
97
|
-
"""Interface definition for the Agent.
|
|
98
|
-
|
|
99
|
-
Attributes:
|
|
100
|
-
inputs: Typed arguments the agent accepts (JSON Schema).
|
|
101
|
-
outputs: Typed structure of the result.
|
|
102
|
-
"""
|
|
103
|
-
|
|
104
|
-
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
105
|
-
|
|
106
|
-
inputs: ImmutableDict = Field(..., description="Typed arguments the agent accepts (JSON Schema).")
|
|
107
|
-
outputs: ImmutableDict = Field(..., description="Typed structure of the result.")
|
|
108
|
-
injected_params: List[str] = Field(default_factory=list, description="List of parameters injected by the system.")
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
class ModelConfig(BaseModel):
|
|
112
|
-
"""LLM Configuration parameters.
|
|
113
|
-
|
|
114
|
-
Attributes:
|
|
115
|
-
model: The LLM model identifier.
|
|
116
|
-
temperature: Temperature for generation.
|
|
117
|
-
"""
|
|
118
|
-
|
|
119
|
-
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
120
|
-
|
|
121
|
-
model: str = Field(..., description="The LLM model identifier.")
|
|
122
|
-
temperature: float = Field(..., ge=0.0, le=2.0, description="Temperature for generation.")
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
class AgentRuntimeConfig(BaseModel):
|
|
126
|
-
"""Configuration of the Agent execution.
|
|
127
|
-
|
|
128
|
-
Attributes:
|
|
129
|
-
nodes: A collection of execution units (Agents, Tools, Logic).
|
|
130
|
-
edges: Directed connections defining control flow.
|
|
131
|
-
entry_point: The ID of the starting node.
|
|
132
|
-
llm_config: Specific LLM parameters.
|
|
133
|
-
"""
|
|
134
|
-
|
|
135
|
-
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
136
|
-
|
|
137
|
-
nodes: List[Node] = Field(..., description="A collection of execution units.")
|
|
138
|
-
edges: List[Edge] = Field(..., description="Directed connections defining control flow.")
|
|
139
|
-
entry_point: str = Field(..., description="The ID of the starting node.")
|
|
140
|
-
llm_config: ModelConfig = Field(..., alias="model_config", description="Specific LLM parameters.")
|
|
141
|
-
|
|
142
|
-
@field_validator("nodes")
|
|
143
|
-
@classmethod
|
|
144
|
-
def validate_unique_node_ids(cls, v: List[Node]) -> List[Node]:
|
|
145
|
-
"""Ensure all node IDs are unique.
|
|
146
|
-
|
|
147
|
-
Args:
|
|
148
|
-
v: The list of nodes to validate.
|
|
149
|
-
|
|
150
|
-
Returns:
|
|
151
|
-
The validated list of nodes.
|
|
152
|
-
|
|
153
|
-
Raises:
|
|
154
|
-
ValueError: If duplicate node IDs are found.
|
|
155
|
-
"""
|
|
156
|
-
ids = [node.id for node in v]
|
|
157
|
-
if len(ids) != len(set(ids)):
|
|
158
|
-
# Find duplicates
|
|
159
|
-
seen = set()
|
|
160
|
-
dupes = set()
|
|
161
|
-
for x in ids:
|
|
162
|
-
if x in seen:
|
|
163
|
-
dupes.add(x)
|
|
164
|
-
seen.add(x)
|
|
165
|
-
raise ValueError(f"Duplicate node IDs found: {', '.join(dupes)}")
|
|
166
|
-
return v
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
class ToolRiskLevel(str, Enum):
|
|
170
|
-
"""Risk level for the tool."""
|
|
171
|
-
|
|
172
|
-
SAFE = "safe"
|
|
173
|
-
STANDARD = "standard"
|
|
174
|
-
CRITICAL = "critical"
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
class ToolRequirement(BaseModel):
|
|
178
|
-
"""Requirement for an MCP tool.
|
|
179
|
-
|
|
180
|
-
Attributes:
|
|
181
|
-
uri: The MCP endpoint URI.
|
|
182
|
-
hash: Integrity check for the tool definition (SHA256).
|
|
183
|
-
scopes: List of permissions required.
|
|
184
|
-
risk_level: The risk level of the tool.
|
|
185
|
-
"""
|
|
186
|
-
|
|
187
|
-
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
188
|
-
|
|
189
|
-
uri: StrictUri = Field(..., description="The MCP endpoint URI.")
|
|
190
|
-
hash: str = Field(
|
|
191
|
-
..., pattern=r"^[a-fA-F0-9]{64}$", description="Integrity check for the tool definition (SHA256)."
|
|
192
|
-
)
|
|
193
|
-
scopes: List[str] = Field(..., description="List of permissions required.")
|
|
194
|
-
risk_level: ToolRiskLevel = Field(..., description="The risk level of the tool.")
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
class AgentDependencies(BaseModel):
|
|
198
|
-
"""External dependencies for the Agent.
|
|
199
|
-
|
|
200
|
-
Attributes:
|
|
201
|
-
tools: List of MCP tool requirements.
|
|
202
|
-
libraries: List of Python packages required (if code execution is allowed).
|
|
203
|
-
"""
|
|
204
|
-
|
|
205
|
-
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
206
|
-
|
|
207
|
-
tools: List[ToolRequirement] = Field(default_factory=list, description="List of MCP tool requirements.")
|
|
208
|
-
libraries: Tuple[str, ...] = Field(
|
|
209
|
-
default_factory=tuple, description="List of Python packages required (if code execution is allowed)."
|
|
210
|
-
)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
class PolicyConfig(BaseModel):
|
|
214
|
-
"""Governance policy configuration.
|
|
215
|
-
|
|
216
|
-
Attributes:
|
|
217
|
-
budget_caps: Dictionary defining budget limits (e.g., {"total_cost": 10.0, "total_tokens": 1000}).
|
|
218
|
-
human_in_the_loop: List of Node IDs that require human approval.
|
|
219
|
-
allowed_domains: List of allowed domains for external access.
|
|
220
|
-
"""
|
|
221
|
-
|
|
222
|
-
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
223
|
-
|
|
224
|
-
budget_caps: Dict[str, float] = Field(default_factory=dict, description="Budget limits.")
|
|
225
|
-
human_in_the_loop: List[str] = Field(default_factory=list, description="Node IDs requiring human approval.")
|
|
226
|
-
allowed_domains: List[str] = Field(default_factory=list, description="Allowed domains for external access.")
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
class TraceLevel(str, Enum):
|
|
230
|
-
"""Level of tracing detail."""
|
|
231
|
-
|
|
232
|
-
FULL = "full"
|
|
233
|
-
METADATA_ONLY = "metadata_only"
|
|
234
|
-
NONE = "none"
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
class ObservabilityConfig(BaseModel):
|
|
238
|
-
"""Observability configuration.
|
|
239
|
-
|
|
240
|
-
Attributes:
|
|
241
|
-
trace_level: Level of tracing detail.
|
|
242
|
-
retention_policy: Retention policy identifier (e.g., '30_days').
|
|
243
|
-
encryption_key_id: Optional ID of the key used for log encryption.
|
|
244
|
-
"""
|
|
245
|
-
|
|
246
|
-
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
247
|
-
|
|
248
|
-
trace_level: TraceLevel = Field(default=TraceLevel.FULL, description="Level of tracing detail.")
|
|
249
|
-
retention_policy: str = Field(default="30_days", description="Retention policy identifier.")
|
|
250
|
-
encryption_key_id: Optional[str] = Field(None, description="Optional ID of the key used for log encryption.")
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
class AgentDefinition(BaseModel):
|
|
254
|
-
"""The Root Object for the CoReason Agent Manifest.
|
|
255
|
-
|
|
256
|
-
Attributes:
|
|
257
|
-
metadata: Metadata for the Agent.
|
|
258
|
-
interface: Interface definition for the Agent.
|
|
259
|
-
config: Configuration of the Agent execution.
|
|
260
|
-
dependencies: External dependencies for the Agent.
|
|
261
|
-
integrity_hash: SHA256 hash of the source code.
|
|
262
|
-
"""
|
|
263
|
-
|
|
264
|
-
model_config = ConfigDict(
|
|
265
|
-
extra="forbid",
|
|
266
|
-
frozen=True,
|
|
267
|
-
title="CoReason Agent Manifest",
|
|
268
|
-
json_schema_extra={
|
|
269
|
-
"$id": "https://coreason.ai/schemas/agent.schema.json",
|
|
270
|
-
"description": "The definitive source of truth for CoReason Agent definitions.",
|
|
271
|
-
},
|
|
272
|
-
)
|
|
273
|
-
|
|
274
|
-
metadata: AgentMetadata
|
|
275
|
-
interface: AgentInterface
|
|
276
|
-
config: AgentRuntimeConfig
|
|
277
|
-
dependencies: AgentDependencies
|
|
278
|
-
policy: Optional[PolicyConfig] = Field(None, description="Governance policy configuration.")
|
|
279
|
-
observability: Optional[ObservabilityConfig] = Field(None, description="Observability configuration.")
|
|
280
|
-
integrity_hash: str = Field(
|
|
281
|
-
...,
|
|
282
|
-
pattern=r"^[a-fA-F0-9]{64}$",
|
|
283
|
-
description="SHA256 hash of the source code.",
|
|
284
|
-
)
|
|
285
|
-
|
|
286
|
-
@model_validator(mode="after")
|
|
287
|
-
def validate_auth_requirements(self) -> AgentDefinition:
|
|
288
|
-
"""Validate that agents requiring auth have user_context injected."""
|
|
289
|
-
if self.metadata.requires_auth:
|
|
290
|
-
if "user_context" not in self.interface.injected_params:
|
|
291
|
-
raise ValueError("Agent requires authentication but 'user_context' is not an injected parameter.")
|
|
292
|
-
return self
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import hashlib
|
|
2
|
-
import json
|
|
3
|
-
from datetime import datetime
|
|
4
|
-
from enum import Enum
|
|
5
|
-
from typing import Any, Dict, List, Optional
|
|
6
|
-
from uuid import UUID
|
|
7
|
-
|
|
8
|
-
from pydantic import BaseModel, ConfigDict, Field
|
|
9
|
-
|
|
10
|
-
from .message import ChatMessage
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class GenAITokenUsage(BaseModel):
|
|
14
|
-
"""Token consumption stats aligned with OTel conventions."""
|
|
15
|
-
|
|
16
|
-
model_config = ConfigDict(extra="ignore")
|
|
17
|
-
|
|
18
|
-
input: int = Field(0, description="Number of input tokens (prompt).")
|
|
19
|
-
output: int = Field(0, description="Number of output tokens (completion).")
|
|
20
|
-
total: int = Field(0, description="Total number of tokens used.")
|
|
21
|
-
|
|
22
|
-
# Backward compatibility fields (mapped to new fields in logic if needed, but kept for schema)
|
|
23
|
-
prompt_tokens: int = 0
|
|
24
|
-
completion_tokens: int = 0
|
|
25
|
-
total_tokens: int = 0
|
|
26
|
-
details: Dict[str, Any] = Field(default_factory=dict)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class GenAIOperation(BaseModel):
|
|
30
|
-
"""An atomic operation in the reasoning process (e.g., one LLM call), aligning with OTel Spans."""
|
|
31
|
-
|
|
32
|
-
model_config = ConfigDict(extra="ignore")
|
|
33
|
-
|
|
34
|
-
span_id: str = Field(..., description="Unique identifier for the operation/span.")
|
|
35
|
-
trace_id: str = Field(..., description="Trace ID this operation belongs to.")
|
|
36
|
-
parent_id: Optional[str] = Field(None, description="Parent span ID.")
|
|
37
|
-
|
|
38
|
-
operation_name: str = Field(..., description="Name of the operation (e.g., chat, embedding).")
|
|
39
|
-
provider: str = Field(..., description="GenAI provider (e.g., openai, anthropic).")
|
|
40
|
-
model: str = Field(..., description="Model name used.")
|
|
41
|
-
|
|
42
|
-
start_time: datetime = Field(default_factory=datetime.now)
|
|
43
|
-
end_time: Optional[datetime] = None
|
|
44
|
-
duration_ms: float = 0.0
|
|
45
|
-
|
|
46
|
-
# Context
|
|
47
|
-
input_messages: List[ChatMessage] = Field(default_factory=list)
|
|
48
|
-
output_messages: List[ChatMessage] = Field(default_factory=list)
|
|
49
|
-
|
|
50
|
-
# Metrics
|
|
51
|
-
token_usage: Optional[GenAITokenUsage] = None
|
|
52
|
-
|
|
53
|
-
# Metadata
|
|
54
|
-
status: str = "pending" # success, error
|
|
55
|
-
error_type: Optional[str] = None
|
|
56
|
-
metadata: Dict[str, Any] = Field(default_factory=dict)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class ReasoningTrace(BaseModel):
|
|
60
|
-
"""The full audit trail of an Agent's execution session.
|
|
61
|
-
|
|
62
|
-
Aligned with OpenTelemetry for trace identification.
|
|
63
|
-
"""
|
|
64
|
-
|
|
65
|
-
model_config = ConfigDict(extra="ignore")
|
|
66
|
-
|
|
67
|
-
trace_id: str = Field(..., description="Trace ID (OTel format).")
|
|
68
|
-
agent_id: str
|
|
69
|
-
session_id: Optional[str] = None
|
|
70
|
-
|
|
71
|
-
start_time: datetime
|
|
72
|
-
end_time: Optional[datetime] = None
|
|
73
|
-
|
|
74
|
-
# The chain of thought (Ordered list of operations)
|
|
75
|
-
steps: List[GenAIOperation] = Field(default_factory=list)
|
|
76
|
-
|
|
77
|
-
# Final outcome
|
|
78
|
-
status: str = "pending" # options: success, failure, pending
|
|
79
|
-
final_result: Optional[str] = None
|
|
80
|
-
error: Optional[str] = None
|
|
81
|
-
|
|
82
|
-
# Aggregated stats
|
|
83
|
-
total_tokens: GenAITokenUsage = Field(default_factory=GenAITokenUsage)
|
|
84
|
-
total_cost: float = 0.0
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
class AuditEventType(str, Enum):
|
|
88
|
-
SYSTEM_CHANGE = "system_change"
|
|
89
|
-
PREDICTION = "prediction"
|
|
90
|
-
GUARDRAIL_TRIGGER = "guardrail_trigger"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
class AuditLog(BaseModel):
|
|
94
|
-
"""Tamper-evident legal record.
|
|
95
|
-
|
|
96
|
-
IDs aligned with OpenTelemetry:
|
|
97
|
-
- audit_id: Unique record ID.
|
|
98
|
-
- trace_id: OTel Trace ID.
|
|
99
|
-
"""
|
|
100
|
-
|
|
101
|
-
audit_id: UUID = Field(..., description="Unique identifier.")
|
|
102
|
-
trace_id: str = Field(..., description="Trace ID for OTel correlation.")
|
|
103
|
-
timestamp: datetime = Field(..., description="ISO8601 timestamp.")
|
|
104
|
-
actor: str = Field(..., description="User ID or Agent Component ID.")
|
|
105
|
-
event_type: AuditEventType = Field(..., description="Type of event.")
|
|
106
|
-
safety_metadata: Dict[str, Any] = Field(..., description="Safety metadata (e.g., PII detected).")
|
|
107
|
-
previous_hash: str = Field(..., description="Hash of the previous log entry.")
|
|
108
|
-
integrity_hash: str = Field(..., description="SHA256 hash of this record + previous_hash.")
|
|
109
|
-
|
|
110
|
-
def compute_hash(self) -> str:
|
|
111
|
-
"""Computes the integrity hash of the record."""
|
|
112
|
-
# Use model_dump to get a dict, but exclude integrity_hash as it is the target
|
|
113
|
-
data = self.model_dump(exclude={"integrity_hash"}, mode="json")
|
|
114
|
-
# Ensure deterministic serialization
|
|
115
|
-
json_str = json.dumps(data, sort_keys=True, default=str)
|
|
116
|
-
return hashlib.sha256(json_str.encode("utf-8")).hexdigest()
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
# --- Backward Compatibility ---
|
|
120
|
-
# Adapters or Aliases
|
|
121
|
-
CognitiveStep = GenAIOperation
|
|
122
|
-
TokenUsage = GenAITokenUsage
|