engrammic-primitives 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.
- engrammic_primitives-0.1.0.dist-info/METADATA +68 -0
- engrammic_primitives-0.1.0.dist-info/RECORD +39 -0
- engrammic_primitives-0.1.0.dist-info/WHEEL +4 -0
- engrammic_primitives-0.1.0.dist-info/licenses/LICENSE +21 -0
- primitives/__init__.py +6 -0
- primitives/eag/__init__.py +44 -0
- primitives/eag/agents/__init__.py +34 -0
- primitives/eag/agents/base.py +135 -0
- primitives/eag/agents/tools.py +77 -0
- primitives/eag/epistemology/__init__.py +45 -0
- primitives/eag/epistemology/confidence.py +138 -0
- primitives/eag/epistemology/promotion.py +119 -0
- primitives/eag/epistemology/supersession.py +119 -0
- primitives/eag/lifecycle.py +127 -0
- primitives/eag/queries/__init__.py +113 -0
- primitives/eag/queries/cluster.py +125 -0
- primitives/eag/queries/ddl.py +82 -0
- primitives/eag/queries/finding.py +164 -0
- primitives/eag/queries/pass_ledger.py +97 -0
- primitives/eag/queries/silo.py +54 -0
- primitives/eag/store.py +87 -0
- primitives/eag/transitions/__init__.py +11 -0
- primitives/eag/transitions/predicates.py +30 -0
- primitives/extensions/__init__.py +1 -0
- primitives/extensions/code.py +41 -0
- primitives/protocols.py +337 -0
- primitives/py.typed +0 -0
- primitives/schema/__init__.py +65 -0
- primitives/schema/edges.py +74 -0
- primitives/schema/labels.py +123 -0
- primitives/scoring/__init__.py +7 -0
- primitives/scoring/decay.py +27 -0
- primitives/shared/__init__.py +32 -0
- primitives/shared/cypher/__init__.py +17 -0
- primitives/shared/cypher/helpers.py +64 -0
- primitives/shared/fingerprints.py +87 -0
- primitives/shared/validators.py +109 -0
- primitives/taxonomy/__init__.py +13 -0
- primitives/taxonomy/categories.py +39 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: engrammic-primitives
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: EAG schema primitives for epistemic context management
|
|
5
|
+
Author-email: Aliasgar Khimani <aliasgar.khimani@engrammic.ai>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: ai-agents,context-management,graphrag,knowledge-graph
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Requires-Python: >=3.13
|
|
16
|
+
Requires-Dist: pydantic>=2.0
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# Engrammic Primitives
|
|
20
|
+
|
|
21
|
+
EAG schema primitives for building epistemic context systems.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install engrammic-primitives
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from primitives.schema import MemoryNode, KnowledgeNode, WisdomNode
|
|
33
|
+
from primitives.eag import CognitiveTier
|
|
34
|
+
|
|
35
|
+
# Create a memory node
|
|
36
|
+
node = MemoryNode(
|
|
37
|
+
content="User prefers dark mode",
|
|
38
|
+
importance=0.7,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# Check cognitive tier
|
|
42
|
+
tier = CognitiveTier.MEMORY
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## When to Use
|
|
46
|
+
|
|
47
|
+
Building your own EAG-compatible system or extending Engrammic.
|
|
48
|
+
|
|
49
|
+
For using Engrammic directly, see:
|
|
50
|
+
- [engrammic-mcp](https://github.com/engrammic/mcp-client) - hosted service
|
|
51
|
+
- [engrammic-engine](https://github.com/engrammic/engine) - local engine
|
|
52
|
+
|
|
53
|
+
## Learn More
|
|
54
|
+
|
|
55
|
+
- [EAG Manifesto](docs/manifesto.md) - the paradigm explained
|
|
56
|
+
|
|
57
|
+
## Modules
|
|
58
|
+
|
|
59
|
+
| Module | Purpose |
|
|
60
|
+
|--------|---------|
|
|
61
|
+
| `primitives.schema` | Node and edge type definitions |
|
|
62
|
+
| `primitives.eag` | EAG-specific implementations |
|
|
63
|
+
| `primitives.protocols` | Storage and lifecycle interfaces |
|
|
64
|
+
| `primitives.scoring` | Decay and freshness formulas |
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
Apache 2.0
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
primitives/__init__.py,sha256=nL6wRTqSdfJnkKV_tEf7Pa7M71gTL22Df6r18cbVccc,136
|
|
2
|
+
primitives/protocols.py,sha256=OalpW1jQq3KvWRg8oG2O_JP9Du1oSLdvrqYW2W-ykW0,8383
|
|
3
|
+
primitives/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
primitives/eag/__init__.py,sha256=yIdHFHIdb0bW7CBsBKT-ZN9q1enZNU4WD3bOL_lV2iE,1119
|
|
5
|
+
primitives/eag/lifecycle.py,sha256=qh78xtbQ5UdFF1DzS9JfkT71YK4IHy1rMnKXmO9gtdY,4454
|
|
6
|
+
primitives/eag/store.py,sha256=nLVl4RfxLjN8sIYGjBgGerHbIeR75T5NgTSC6iIaVII,2509
|
|
7
|
+
primitives/eag/agents/__init__.py,sha256=OPTv2TMGrbXBINTgB4lwrzXM6oyy4yHs0cKLMegtusU,712
|
|
8
|
+
primitives/eag/agents/base.py,sha256=FZfQyxRT_OhwgYtddRD9vVAnym-VGFQ14CHwHt_imMk,3223
|
|
9
|
+
primitives/eag/agents/tools.py,sha256=z8QpyMCKRVr_sv1rd9pNwE__xHiMe8FsldWG1yfTvsM,1980
|
|
10
|
+
primitives/eag/epistemology/__init__.py,sha256=5q3C1Gbe-iIRbKltVj9V0D0pAVDIo6sKiNZ6ujkooAc,1071
|
|
11
|
+
primitives/eag/epistemology/confidence.py,sha256=fc5Ye3jMh2LzV6gnAgNhcYa0jOcS84WoiInjOsaY39Q,4177
|
|
12
|
+
primitives/eag/epistemology/promotion.py,sha256=d816t1oPA3DsmCoKuV8glXo4-cQJixF4_T1Ln2ClJzA,3437
|
|
13
|
+
primitives/eag/epistemology/supersession.py,sha256=hPwVSQyJaCfaistSy7BoKo11R1215pBW1QLaeMcqflA,3653
|
|
14
|
+
primitives/eag/queries/__init__.py,sha256=A8UMF_uS8u311WaiyMrwBdlEL7nnVQT9qwEJX4lzJqc,2706
|
|
15
|
+
primitives/eag/queries/cluster.py,sha256=aZRkGmq2Kd614qydtLc5QbwGix8B7XvbQd_HYcodH3U,3301
|
|
16
|
+
primitives/eag/queries/ddl.py,sha256=bavztY-QGWZmOoIITCrjNczC8KiMRxATXaVxtG5QVFU,2512
|
|
17
|
+
primitives/eag/queries/finding.py,sha256=Y5mjKYH0_WmSxcVjAAzWHh1ntidrNNSHCerZ-SBVItg,4948
|
|
18
|
+
primitives/eag/queries/pass_ledger.py,sha256=oereFR-5SNrCR7EjsF-5PraB4l71KhHWz5zOoKz9Kjs,2361
|
|
19
|
+
primitives/eag/queries/silo.py,sha256=yW7hn2eU_941X0b8AP4Ji9_6UTP2S_KAm0VN4uErfbs,1098
|
|
20
|
+
primitives/eag/transitions/__init__.py,sha256=EUWoZxpvZAyX9WKAy9VO0qVhzVmMzqDoalgKyf1a_yk,243
|
|
21
|
+
primitives/eag/transitions/predicates.py,sha256=MpYTo-2NBv6OQnPQt2zUa_lx0I9ToCnDtE1tr05zYoo,787
|
|
22
|
+
primitives/extensions/__init__.py,sha256=prvW-U5XrULsOS4mq-2CXPOAlGWpMEZFwQ6SNc-4U9o,57
|
|
23
|
+
primitives/extensions/code.py,sha256=cSQfJKhDEUBy5ZG5c2_uGfj1MR3pFcyVoQIcB-UkD2A,1001
|
|
24
|
+
primitives/schema/__init__.py,sha256=jrtgvFhruq4XCkioXIqPeODMWNuEgOCb1Jb8hdPRs9M,1348
|
|
25
|
+
primitives/schema/edges.py,sha256=RrdDeDgOK6wmH3W5synfEc-_pQFcClgNRMmqFUpQrKE,1769
|
|
26
|
+
primitives/schema/labels.py,sha256=z5z_01sDU59Q2xpTavJ-RSnx3lLSUO-4nNyS6gEHx_s,3635
|
|
27
|
+
primitives/scoring/__init__.py,sha256=T-3fWDlMGkoo-SPK23eMtIVgkAiKu85bMiZvv9Vnm9c,189
|
|
28
|
+
primitives/scoring/decay.py,sha256=T1UNZ-5tFmwGl-1v0ri9hhLM-yO3m8hqziX4WnccX10,687
|
|
29
|
+
primitives/shared/__init__.py,sha256=zghiwCEcKdwaHdVJIwFBsg9M9_XfBYSKbisDFRnUqSs,796
|
|
30
|
+
primitives/shared/fingerprints.py,sha256=BONc4mKj0MuC-UcAMyOM3OhXBNz_8ZaqJubf4ZWLlnM,2347
|
|
31
|
+
primitives/shared/validators.py,sha256=hkYvoTeNaURGeDUCnjYhDQLr_G4Blc_LQ-p12U37GAY,2946
|
|
32
|
+
primitives/shared/cypher/__init__.py,sha256=gNTqo9P89Ue3uRQzAgRFnWoo7hiijL8FtinY4T52OPw,362
|
|
33
|
+
primitives/shared/cypher/helpers.py,sha256=ciL7AwKXUOklIigRrRA0AC1NKIaVnfY0P3RtbkdV-BA,1558
|
|
34
|
+
primitives/taxonomy/__init__.py,sha256=8EaCStzHThSHkxO-N1X_A3rBmcfUx-p5vVQa-JE_aqE,263
|
|
35
|
+
primitives/taxonomy/categories.py,sha256=44tuSkYTcmwdaYXwUjuonGPwR3k045aJofDneHPjzfM,887
|
|
36
|
+
engrammic_primitives-0.1.0.dist-info/METADATA,sha256=JV-G9b-O1z-B7Q2SpCHSWkcou4iJuvYarR9z52bNoaY,1795
|
|
37
|
+
engrammic_primitives-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
38
|
+
engrammic_primitives-0.1.0.dist-info/licenses/LICENSE,sha256=esUnW0wDJTg5GnYzhkHmYMUpyPvOfw9Uu1xew_bTn24,1068
|
|
39
|
+
engrammic_primitives-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Delta Prime
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
primitives/__init__.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""EAG (Epistemic Augmented Generation) implementation.
|
|
2
|
+
|
|
3
|
+
Four-layer cognitive architecture: Memory -> Knowledge -> Wisdom -> Intelligence.
|
|
4
|
+
Implements the protocol interfaces with EAG-specific semantics.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# Epistemology exports
|
|
8
|
+
from primitives.eag.epistemology import (
|
|
9
|
+
ClaimForPromotion,
|
|
10
|
+
ContradictionResult,
|
|
11
|
+
PromotionDecision,
|
|
12
|
+
PromotionRule,
|
|
13
|
+
SourceTier,
|
|
14
|
+
SupersessionDecision,
|
|
15
|
+
combined_confidence,
|
|
16
|
+
detect_contradiction,
|
|
17
|
+
incremental_noisy_or,
|
|
18
|
+
noisy_or_aggregate,
|
|
19
|
+
should_promote_r1,
|
|
20
|
+
should_promote_r2,
|
|
21
|
+
should_supersede,
|
|
22
|
+
)
|
|
23
|
+
from primitives.eag.lifecycle import EAGLifecycleManager
|
|
24
|
+
from primitives.eag.store import EAGKnowledgeStore
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
# Epistemology
|
|
28
|
+
"SourceTier",
|
|
29
|
+
"combined_confidence",
|
|
30
|
+
"noisy_or_aggregate",
|
|
31
|
+
"incremental_noisy_or",
|
|
32
|
+
"PromotionRule",
|
|
33
|
+
"ClaimForPromotion",
|
|
34
|
+
"PromotionDecision",
|
|
35
|
+
"should_promote_r1",
|
|
36
|
+
"should_promote_r2",
|
|
37
|
+
"ContradictionResult",
|
|
38
|
+
"detect_contradiction",
|
|
39
|
+
"should_supersede",
|
|
40
|
+
"SupersessionDecision",
|
|
41
|
+
# Implementations
|
|
42
|
+
"EAGKnowledgeStore",
|
|
43
|
+
"EAGLifecycleManager",
|
|
44
|
+
]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""EAG Agent Protocol definitions.
|
|
2
|
+
|
|
3
|
+
Defines abstract interfaces for EAG agents and tools. Implementations
|
|
4
|
+
live in private repositories (context-service); this module provides
|
|
5
|
+
the protocol contract that implementations must follow.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from primitives.eag.agents.base import (
|
|
9
|
+
AgentConfig,
|
|
10
|
+
AgentPhase,
|
|
11
|
+
AgentProtocol,
|
|
12
|
+
AgentResult,
|
|
13
|
+
BudgetConfig,
|
|
14
|
+
BudgetStatus,
|
|
15
|
+
DepsProtocol,
|
|
16
|
+
)
|
|
17
|
+
from primitives.eag.agents.tools import (
|
|
18
|
+
ToolDefinition,
|
|
19
|
+
ToolProtocol,
|
|
20
|
+
ToolResult,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"AgentConfig",
|
|
25
|
+
"AgentPhase",
|
|
26
|
+
"AgentProtocol",
|
|
27
|
+
"AgentResult",
|
|
28
|
+
"BudgetConfig",
|
|
29
|
+
"BudgetStatus",
|
|
30
|
+
"DepsProtocol",
|
|
31
|
+
"ToolDefinition",
|
|
32
|
+
"ToolProtocol",
|
|
33
|
+
"ToolResult",
|
|
34
|
+
]
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Base protocol definitions for EAG agents.
|
|
2
|
+
|
|
3
|
+
Agents in EAG operate in phases (fast, plan, deep, stitch), each with
|
|
4
|
+
distinct output types and budget constraints. This module defines the
|
|
5
|
+
abstract interfaces; implementations are private.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from abc import abstractmethod
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from enum import StrEnum
|
|
13
|
+
from typing import TYPE_CHECKING, Any, Generic, Protocol, TypeVar, runtime_checkable
|
|
14
|
+
|
|
15
|
+
from pydantic import BaseModel, ConfigDict
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from primitives.eag.agents.tools import ToolProtocol
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AgentPhase(StrEnum):
|
|
22
|
+
"""Visit phases for EAG agents."""
|
|
23
|
+
|
|
24
|
+
FAST = "fast"
|
|
25
|
+
PLAN = "plan"
|
|
26
|
+
DEEP = "deep"
|
|
27
|
+
STITCH = "stitch"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class BudgetStatus(BaseModel):
|
|
31
|
+
"""Budget state exposed to agents in tool responses."""
|
|
32
|
+
|
|
33
|
+
model_config = ConfigDict(extra="forbid")
|
|
34
|
+
|
|
35
|
+
tokens_remaining: int
|
|
36
|
+
tool_calls_remaining: int
|
|
37
|
+
wrap_up_signal: bool
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class BudgetConfig:
|
|
42
|
+
"""Per-phase budget configuration."""
|
|
43
|
+
|
|
44
|
+
nominal_tokens: int
|
|
45
|
+
hard_tokens: int
|
|
46
|
+
tool_calls_limit: int
|
|
47
|
+
request_limit: int
|
|
48
|
+
soft_signal_ratio: float = 0.69
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass
|
|
52
|
+
class AgentConfig:
|
|
53
|
+
"""Configuration for an agent instance."""
|
|
54
|
+
|
|
55
|
+
phase: AgentPhase
|
|
56
|
+
model: str
|
|
57
|
+
budget: BudgetConfig
|
|
58
|
+
retries: int = 8
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
T = TypeVar("T")
|
|
62
|
+
DepsT = TypeVar("DepsT", bound="DepsProtocol")
|
|
63
|
+
OutputT = TypeVar("OutputT")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@runtime_checkable
|
|
67
|
+
class DepsProtocol(Protocol):
|
|
68
|
+
"""Minimal interface for per-visit dependencies.
|
|
69
|
+
|
|
70
|
+
Implementations carry org/silo/cluster context, buffer for committed
|
|
71
|
+
artifacts, and infrastructure handles. The protocol defines only the
|
|
72
|
+
fields that tools and result types depend on.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
org_id: str
|
|
76
|
+
silo_id: str
|
|
77
|
+
cluster_id: str
|
|
78
|
+
pass_id: str
|
|
79
|
+
seen_node_ids: set[str]
|
|
80
|
+
budget: BudgetStatus
|
|
81
|
+
finalized: bool
|
|
82
|
+
|
|
83
|
+
def record_commit(self, event: dict[str, Any]) -> None:
|
|
84
|
+
"""Append an event to the commit log."""
|
|
85
|
+
...
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclass
|
|
89
|
+
class AgentResult(Generic[T]):
|
|
90
|
+
"""Result from an agent run."""
|
|
91
|
+
|
|
92
|
+
output: T
|
|
93
|
+
finalized: bool
|
|
94
|
+
claims_committed: int
|
|
95
|
+
edges_committed: int
|
|
96
|
+
rejections: int
|
|
97
|
+
tokens_used: int
|
|
98
|
+
tool_calls_used: int
|
|
99
|
+
commit_log: list[dict[str, Any]] = field(default_factory=list)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@runtime_checkable
|
|
103
|
+
class AgentProtocol(Protocol[DepsT, OutputT]):
|
|
104
|
+
"""Protocol for EAG agents.
|
|
105
|
+
|
|
106
|
+
An agent encapsulates a model, system prompt, output type, and budget
|
|
107
|
+
constraints. Tools are registered separately via the ToolProtocol.
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def phase(self) -> AgentPhase:
|
|
112
|
+
"""The phase this agent operates in."""
|
|
113
|
+
...
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def config(self) -> AgentConfig:
|
|
117
|
+
"""Agent configuration."""
|
|
118
|
+
...
|
|
119
|
+
|
|
120
|
+
@abstractmethod
|
|
121
|
+
async def run(
|
|
122
|
+
self,
|
|
123
|
+
deps: DepsT,
|
|
124
|
+
user_prompt: str,
|
|
125
|
+
) -> AgentResult[OutputT]:
|
|
126
|
+
"""Execute the agent with the given dependencies and prompt.
|
|
127
|
+
|
|
128
|
+
The agent runs until it produces an output, calls finalize, or
|
|
129
|
+
exhausts its budget. Tools mutate deps in place.
|
|
130
|
+
"""
|
|
131
|
+
...
|
|
132
|
+
|
|
133
|
+
def register_tool(self, tool: ToolProtocol[DepsT]) -> None:
|
|
134
|
+
"""Register a tool on this agent."""
|
|
135
|
+
...
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Tool protocol definitions for EAG agents.
|
|
2
|
+
|
|
3
|
+
Tools are functions that agents call to read state, commit artifacts, or
|
|
4
|
+
signal completion. Each tool call updates the budget and may mutate the
|
|
5
|
+
dependency container.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from abc import abstractmethod
|
|
11
|
+
from typing import Any, Protocol, TypeVar, runtime_checkable
|
|
12
|
+
|
|
13
|
+
from pydantic import BaseModel, ConfigDict
|
|
14
|
+
|
|
15
|
+
from primitives.eag.agents.base import BudgetStatus, DepsProtocol
|
|
16
|
+
|
|
17
|
+
DepsT = TypeVar("DepsT", bound=DepsProtocol)
|
|
18
|
+
ResultT = TypeVar("ResultT")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ToolResult(BaseModel):
|
|
22
|
+
"""Base class for tool results. All results carry budget status."""
|
|
23
|
+
|
|
24
|
+
model_config = ConfigDict(extra="forbid")
|
|
25
|
+
|
|
26
|
+
budget_status: BudgetStatus
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ToolDefinition(BaseModel):
|
|
30
|
+
"""Metadata describing a tool for schema generation."""
|
|
31
|
+
|
|
32
|
+
model_config = ConfigDict(extra="forbid")
|
|
33
|
+
|
|
34
|
+
name: str
|
|
35
|
+
description: str
|
|
36
|
+
parameters_schema: dict[str, Any]
|
|
37
|
+
result_schema: dict[str, Any]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@runtime_checkable
|
|
41
|
+
class ToolProtocol(Protocol[DepsT]): # type: ignore[misc]
|
|
42
|
+
"""Protocol for EAG agent tools.
|
|
43
|
+
|
|
44
|
+
Tools are async callables that receive a context (containing deps)
|
|
45
|
+
and arguments, returning a result that includes budget status.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def name(self) -> str:
|
|
50
|
+
"""Tool name as exposed to the agent."""
|
|
51
|
+
...
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def description(self) -> str:
|
|
55
|
+
"""Description shown to the agent."""
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def definition(self) -> ToolDefinition:
|
|
60
|
+
"""Full tool definition for schema generation."""
|
|
61
|
+
...
|
|
62
|
+
|
|
63
|
+
@abstractmethod
|
|
64
|
+
async def __call__(
|
|
65
|
+
self,
|
|
66
|
+
deps: DepsT,
|
|
67
|
+
**kwargs: Any,
|
|
68
|
+
) -> ToolResult:
|
|
69
|
+
"""Execute the tool.
|
|
70
|
+
|
|
71
|
+
Implementations should:
|
|
72
|
+
1. Perform the operation (read, commit, etc.)
|
|
73
|
+
2. Update deps.seen_node_ids if nodes were returned
|
|
74
|
+
3. Rebuild the budget status
|
|
75
|
+
4. Return a result with the updated budget
|
|
76
|
+
"""
|
|
77
|
+
...
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Epistemology primitives: confidence, promotion, supersession.
|
|
2
|
+
|
|
3
|
+
All functions here are pure and deterministic. No LLM calls happen
|
|
4
|
+
at adjudication time.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from primitives.eag.epistemology.confidence import (
|
|
8
|
+
SourceTier,
|
|
9
|
+
combined_confidence,
|
|
10
|
+
incremental_noisy_or,
|
|
11
|
+
noisy_or_aggregate,
|
|
12
|
+
partial_confidence,
|
|
13
|
+
)
|
|
14
|
+
from primitives.eag.epistemology.promotion import (
|
|
15
|
+
ClaimForPromotion,
|
|
16
|
+
PromotionDecision,
|
|
17
|
+
PromotionRule,
|
|
18
|
+
should_promote_r1,
|
|
19
|
+
should_promote_r2,
|
|
20
|
+
)
|
|
21
|
+
from primitives.eag.epistemology.supersession import (
|
|
22
|
+
ContradictionResult,
|
|
23
|
+
FactForSupersession,
|
|
24
|
+
SupersessionDecision,
|
|
25
|
+
detect_contradiction,
|
|
26
|
+
should_supersede,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"SourceTier",
|
|
31
|
+
"combined_confidence",
|
|
32
|
+
"noisy_or_aggregate",
|
|
33
|
+
"incremental_noisy_or",
|
|
34
|
+
"partial_confidence",
|
|
35
|
+
"PromotionRule",
|
|
36
|
+
"ClaimForPromotion",
|
|
37
|
+
"PromotionDecision",
|
|
38
|
+
"should_promote_r1",
|
|
39
|
+
"should_promote_r2",
|
|
40
|
+
"ContradictionResult",
|
|
41
|
+
"FactForSupersession",
|
|
42
|
+
"SupersessionDecision",
|
|
43
|
+
"detect_contradiction",
|
|
44
|
+
"should_supersede",
|
|
45
|
+
]
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""Confidence computation primitives.
|
|
2
|
+
|
|
3
|
+
Pure functions for computing claim and aggregate confidence scores.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from enum import StrEnum
|
|
9
|
+
from functools import reduce
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SourceTier(StrEnum):
|
|
13
|
+
"""Source credibility tiers with associated weights."""
|
|
14
|
+
|
|
15
|
+
AUTHORITATIVE = "authoritative" # 1.0
|
|
16
|
+
VALIDATED = "validated" # 0.85
|
|
17
|
+
COMMUNITY = "community" # 0.6
|
|
18
|
+
UNKNOWN = "unknown" # 0.4
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def weight(self) -> float:
|
|
22
|
+
return _TIER_WEIGHTS[self]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
_TIER_WEIGHTS: dict[SourceTier, float] = {
|
|
26
|
+
SourceTier.AUTHORITATIVE: 1.0,
|
|
27
|
+
SourceTier.VALIDATED: 0.85,
|
|
28
|
+
SourceTier.COMMUNITY: 0.6,
|
|
29
|
+
SourceTier.UNKNOWN: 0.4,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def combined_confidence(
|
|
34
|
+
raw_confidence: float,
|
|
35
|
+
source_tier: SourceTier,
|
|
36
|
+
corroboration_factor: float = 1.0,
|
|
37
|
+
method_weight: float = 1.0,
|
|
38
|
+
) -> float:
|
|
39
|
+
"""Compute combined confidence for a single claim.
|
|
40
|
+
|
|
41
|
+
Formula: source_tier * corroboration_factor * method_weight * raw_confidence
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
raw_confidence: Base confidence from extraction (0.0 - 1.0)
|
|
45
|
+
source_tier: Credibility tier of the source
|
|
46
|
+
corroboration_factor: Boost from corroborating evidence (default 1.0)
|
|
47
|
+
method_weight: Weight based on extraction method (default 1.0)
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Combined confidence score (0.0 - 1.0)
|
|
51
|
+
"""
|
|
52
|
+
result = source_tier.weight * corroboration_factor * method_weight * raw_confidence
|
|
53
|
+
return min(max(result, 0.0), 1.0)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def noisy_or_aggregate(confidences: list[float], cap: float = 0.99) -> float:
|
|
57
|
+
"""Aggregate multiple confidence scores using noisy-OR.
|
|
58
|
+
|
|
59
|
+
Formula: 1 - product(1 - c_i) for each confidence c_i
|
|
60
|
+
|
|
61
|
+
This models independent evidence: each source has a chance of being
|
|
62
|
+
correct, and we want the probability that at least one is correct.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
confidences: List of individual confidence scores
|
|
66
|
+
cap: Maximum return value (default 0.99)
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Aggregated confidence score, capped at `cap`
|
|
70
|
+
"""
|
|
71
|
+
if not confidences:
|
|
72
|
+
return 0.0
|
|
73
|
+
|
|
74
|
+
# 1 - product(1 - c_i)
|
|
75
|
+
complement_product = reduce(lambda acc, c: acc * (1 - c), confidences, 1.0)
|
|
76
|
+
result = 1 - complement_product
|
|
77
|
+
|
|
78
|
+
return min(result, cap)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
_EPISTEMIC_DISCOUNT: float = 0.7
|
|
82
|
+
"""Discount applied to uncorroborated single-source claims.
|
|
83
|
+
|
|
84
|
+
A claim supported by only one source has inherent uncertainty that
|
|
85
|
+
corroboration resolves. This factor represents the pre-corroboration
|
|
86
|
+
epistemic penalty.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def partial_confidence(
|
|
91
|
+
raw_confidence: float,
|
|
92
|
+
source_reliability: float = 1.0,
|
|
93
|
+
) -> float:
|
|
94
|
+
"""Compute pre-corroboration confidence for a single-source claim.
|
|
95
|
+
|
|
96
|
+
Used when storing a Claim before corroboration has occurred. The result
|
|
97
|
+
is a provisional score; once the claim is corroborated and promoted to
|
|
98
|
+
a Fact, `combined_confidence` should be used to derive the final score.
|
|
99
|
+
|
|
100
|
+
Formula: raw_confidence * source_reliability * EPISTEMIC_DISCOUNT (0.7)
|
|
101
|
+
|
|
102
|
+
The 0.7 epistemic discount reflects that single-source claims carry
|
|
103
|
+
inherent uncertainty regardless of source quality. Corroboration by
|
|
104
|
+
independent sources removes this discount.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
raw_confidence: Base confidence from extraction (0.0 - 1.0).
|
|
108
|
+
source_reliability: Reliability multiplier for the source (0.0 - 1.0,
|
|
109
|
+
default 1.0 for an unqualified source).
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
Provisional confidence score clamped to [0.0, 1.0].
|
|
113
|
+
"""
|
|
114
|
+
result = raw_confidence * source_reliability * _EPISTEMIC_DISCOUNT
|
|
115
|
+
return min(max(result, 0.0), 1.0)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def incremental_noisy_or(
|
|
119
|
+
current_aggregate: float,
|
|
120
|
+
new_confidence: float,
|
|
121
|
+
cap: float = 0.99,
|
|
122
|
+
) -> float:
|
|
123
|
+
"""Incrementally update a noisy-OR aggregate with a new confidence.
|
|
124
|
+
|
|
125
|
+
Equivalent to recomputing from scratch but O(1) instead of O(n).
|
|
126
|
+
|
|
127
|
+
Formula: 1 - (1 - current) * (1 - new)
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
current_aggregate: Existing aggregated confidence
|
|
131
|
+
new_confidence: New confidence to incorporate
|
|
132
|
+
cap: Maximum return value (default 0.99)
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Updated aggregated confidence
|
|
136
|
+
"""
|
|
137
|
+
result = 1 - (1 - current_aggregate) * (1 - new_confidence)
|
|
138
|
+
return min(result, cap)
|