lians-sdk 0.1.3__tar.gz

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.
@@ -0,0 +1,47 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ *.egg
6
+ .venv/
7
+ venv/
8
+ env/
9
+ .env
10
+ dist/
11
+ build/
12
+ *.whl
13
+
14
+ # Test / coverage
15
+ .pytest_cache/
16
+ .coverage
17
+ htmlcov/
18
+
19
+ # IDE
20
+ .idea/
21
+ .vscode/
22
+ *.sublime-project
23
+ *.sublime-workspace
24
+
25
+ # OS
26
+ .DS_Store
27
+ Thumbs.db
28
+
29
+ # Windows binaries / assemblies
30
+ *.exe
31
+ *.winmd
32
+ *.dll
33
+ *.pdb
34
+
35
+ # Claude Code local settings
36
+ .claude/
37
+
38
+ # Internal working documents (not client-facing)
39
+ SCALE.md
40
+ BUILD.md
41
+ MARKET.md
42
+
43
+ # Personal files
44
+ *.pdf
45
+
46
+ # Node
47
+ node_modules/
@@ -0,0 +1,146 @@
1
+ Metadata-Version: 2.4
2
+ Name: lians-sdk
3
+ Version: 0.1.3
4
+ Summary: Financial-grade AI memory — bitemporal facts, SEC 17a-4 audit chain, GDPR crypto-shred
5
+ Project-URL: Homepage, https://github.com/ebeirne/Lians
6
+ Project-URL: Repository, https://github.com/ebeirne/Lians
7
+ Project-URL: Documentation, https://github.com/ebeirne/Lians#readme
8
+ License: Apache-2.0
9
+ Keywords: agents,ai,bitemporal,compliance,crewai,finance,langchain,langgraph,memory
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Financial and Insurance Industry
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Office/Business :: Financial
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: httpx>=0.25
22
+ Provides-Extra: all
23
+ Requires-Dist: aiosqlite>=0.19; extra == 'all'
24
+ Requires-Dist: autogen-core>=0.4; extra == 'all'
25
+ Requires-Dist: crewai>=0.28; extra == 'all'
26
+ Requires-Dist: httpx>=0.27.0; extra == 'all'
27
+ Requires-Dist: langchain-core>=0.2; extra == 'all'
28
+ Requires-Dist: langgraph>=0.1; extra == 'all'
29
+ Requires-Dist: mcp>=1.0.0; extra == 'all'
30
+ Requires-Dist: openai-agents>=0.0.1; extra == 'all'
31
+ Requires-Dist: sqlalchemy>=2.0; extra == 'all'
32
+ Provides-Extra: autogen
33
+ Requires-Dist: autogen-core>=0.4; extra == 'autogen'
34
+ Provides-Extra: crewai
35
+ Requires-Dist: crewai>=0.28; extra == 'crewai'
36
+ Provides-Extra: langchain
37
+ Requires-Dist: langchain-core>=0.2; extra == 'langchain'
38
+ Provides-Extra: langgraph
39
+ Requires-Dist: langchain-core>=0.2; extra == 'langgraph'
40
+ Requires-Dist: langgraph>=0.1; extra == 'langgraph'
41
+ Provides-Extra: local
42
+ Requires-Dist: aiosqlite>=0.19; extra == 'local'
43
+ Requires-Dist: sqlalchemy>=2.0; extra == 'local'
44
+ Provides-Extra: mcp
45
+ Requires-Dist: httpx>=0.27.0; extra == 'mcp'
46
+ Requires-Dist: mcp>=1.0.0; extra == 'mcp'
47
+ Provides-Extra: openai-agents
48
+ Requires-Dist: openai-agents>=0.0.1; extra == 'openai-agents'
49
+ Description-Content-Type: text/markdown
50
+
51
+ # Lians (蓮)
52
+
53
+ **Financial-grade AI memory** — bitemporal facts, SEC 17a-4 audit chain, GDPR crypto-shred.
54
+
55
+ ## Install
56
+
57
+ ```bash
58
+ pip install lians-sdk # HTTP client only
59
+ pip install lians-sdk[local] # + zero-setup SQLite mode (no server needed)
60
+ pip install lians-sdk[langchain] # + LangChain chat history & tools
61
+ pip install lians-sdk[langgraph] # + LangGraph node factories
62
+ pip install lians-sdk[crewai] # + CrewAI BaseTool wrappers
63
+ pip install lians-sdk[openai-agents] # + OpenAI Agents SDK tools
64
+ pip install lians-sdk[autogen] # + AutoGen v0.4 tools
65
+ pip install lians-sdk[all] # Everything
66
+ ```
67
+
68
+ ## Quickstart
69
+
70
+ ```python
71
+ from lians import LocalLiansClient
72
+ from datetime import datetime, timezone
73
+
74
+ mem = LocalLiansClient() # no server, no Docker, no API key
75
+
76
+ mem.add(
77
+ agent_id="analyst-1",
78
+ content="NVDA FY2026 revenue guidance raised to $40B",
79
+ event_time=datetime(2025, 11, 19, 16, tzinfo=timezone.utc),
80
+ metadata={"ticker": "NVDA", "metric": "revenue_guidance"},
81
+ importance=0.9,
82
+ )
83
+
84
+ # Superseded facts are excluded at the DB layer — LLM never sees stale data
85
+ result = mem.recall(agent_id="analyst-1", query="NVDA revenue guidance")
86
+
87
+ # Point-in-time: what did we know on March 1?
88
+ result = mem.recall_at(
89
+ agent_id="analyst-1",
90
+ query="NVDA revenue guidance",
91
+ as_of=datetime(2025, 3, 1, tzinfo=timezone.utc),
92
+ )
93
+
94
+ # Extract memories directly from a conversation (like mem0.add(messages=[...]))
95
+ mem.add_from_messages(
96
+ agent_id="analyst-1",
97
+ messages=[
98
+ {"role": "user", "content": "What guidance did NVDA give?"},
99
+ {"role": "assistant", "content": "NVDA raised FY2026 revenue guidance to $40B."},
100
+ ],
101
+ )
102
+ ```
103
+
104
+ ## What makes Lians different
105
+
106
+ | Feature | Lians | mem0 | Graphiti/Zep |
107
+ |---------|------|------|-------------|
108
+ | Bitemporal model (event + ingestion time) | ✓ | ✗ | ✓ |
109
+ | Supersession (stale facts excluded at DB layer) | ✓ | ✗ | Partial |
110
+ | SEC 17a-4 tamper-evident audit chain | ✓ | ✗ | ✗ |
111
+ | GDPR crypto-shred with audit survival | ✓ | ✗ | ✗ |
112
+ | Information barriers (PostgreSQL RLS) | ✓ | ✗ | ✗ |
113
+ | Backtest contamination detection | ✓ | ✗ | ✗ |
114
+
115
+ ## Framework integrations
116
+
117
+ ```python
118
+ # LangChain
119
+ from lians.langchain_integration import LiansChatHistory, build_tools
120
+
121
+ # LangGraph
122
+ from lians.langgraph_integration import create_recall_node, create_remember_node
123
+
124
+ # CrewAI
125
+ from lians.crewai_integration import build_crewai_tools
126
+
127
+ # OpenAI Agents SDK
128
+ from lians.openai_agents_integration import build_openai_agent_tools
129
+
130
+ # AutoGen v0.4
131
+ from lians.autogen_integration import build_autogen_tools
132
+ ```
133
+
134
+ ## Switching to hosted API
135
+
136
+ ```python
137
+ # Dev (local SQLite, no server)
138
+ from lians import LocalLiansClient
139
+ mem = LocalLiansClient()
140
+
141
+ # Production (self-hosted or managed)
142
+ from lians import LiansClient
143
+ mem = LiansClient(base_url="https://mem.yourfirm.internal", api_key="...")
144
+ ```
145
+
146
+ Full documentation: [github.com/ebeirne/Lians](https://github.com/ebeirne/Lians)
@@ -0,0 +1,96 @@
1
+ # Lians (蓮)
2
+
3
+ **Financial-grade AI memory** — bitemporal facts, SEC 17a-4 audit chain, GDPR crypto-shred.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install lians-sdk # HTTP client only
9
+ pip install lians-sdk[local] # + zero-setup SQLite mode (no server needed)
10
+ pip install lians-sdk[langchain] # + LangChain chat history & tools
11
+ pip install lians-sdk[langgraph] # + LangGraph node factories
12
+ pip install lians-sdk[crewai] # + CrewAI BaseTool wrappers
13
+ pip install lians-sdk[openai-agents] # + OpenAI Agents SDK tools
14
+ pip install lians-sdk[autogen] # + AutoGen v0.4 tools
15
+ pip install lians-sdk[all] # Everything
16
+ ```
17
+
18
+ ## Quickstart
19
+
20
+ ```python
21
+ from lians import LocalLiansClient
22
+ from datetime import datetime, timezone
23
+
24
+ mem = LocalLiansClient() # no server, no Docker, no API key
25
+
26
+ mem.add(
27
+ agent_id="analyst-1",
28
+ content="NVDA FY2026 revenue guidance raised to $40B",
29
+ event_time=datetime(2025, 11, 19, 16, tzinfo=timezone.utc),
30
+ metadata={"ticker": "NVDA", "metric": "revenue_guidance"},
31
+ importance=0.9,
32
+ )
33
+
34
+ # Superseded facts are excluded at the DB layer — LLM never sees stale data
35
+ result = mem.recall(agent_id="analyst-1", query="NVDA revenue guidance")
36
+
37
+ # Point-in-time: what did we know on March 1?
38
+ result = mem.recall_at(
39
+ agent_id="analyst-1",
40
+ query="NVDA revenue guidance",
41
+ as_of=datetime(2025, 3, 1, tzinfo=timezone.utc),
42
+ )
43
+
44
+ # Extract memories directly from a conversation (like mem0.add(messages=[...]))
45
+ mem.add_from_messages(
46
+ agent_id="analyst-1",
47
+ messages=[
48
+ {"role": "user", "content": "What guidance did NVDA give?"},
49
+ {"role": "assistant", "content": "NVDA raised FY2026 revenue guidance to $40B."},
50
+ ],
51
+ )
52
+ ```
53
+
54
+ ## What makes Lians different
55
+
56
+ | Feature | Lians | mem0 | Graphiti/Zep |
57
+ |---------|------|------|-------------|
58
+ | Bitemporal model (event + ingestion time) | ✓ | ✗ | ✓ |
59
+ | Supersession (stale facts excluded at DB layer) | ✓ | ✗ | Partial |
60
+ | SEC 17a-4 tamper-evident audit chain | ✓ | ✗ | ✗ |
61
+ | GDPR crypto-shred with audit survival | ✓ | ✗ | ✗ |
62
+ | Information barriers (PostgreSQL RLS) | ✓ | ✗ | ✗ |
63
+ | Backtest contamination detection | ✓ | ✗ | ✗ |
64
+
65
+ ## Framework integrations
66
+
67
+ ```python
68
+ # LangChain
69
+ from lians.langchain_integration import LiansChatHistory, build_tools
70
+
71
+ # LangGraph
72
+ from lians.langgraph_integration import create_recall_node, create_remember_node
73
+
74
+ # CrewAI
75
+ from lians.crewai_integration import build_crewai_tools
76
+
77
+ # OpenAI Agents SDK
78
+ from lians.openai_agents_integration import build_openai_agent_tools
79
+
80
+ # AutoGen v0.4
81
+ from lians.autogen_integration import build_autogen_tools
82
+ ```
83
+
84
+ ## Switching to hosted API
85
+
86
+ ```python
87
+ # Dev (local SQLite, no server)
88
+ from lians import LocalLiansClient
89
+ mem = LocalLiansClient()
90
+
91
+ # Production (self-hosted or managed)
92
+ from lians import LiansClient
93
+ mem = LiansClient(base_url="https://mem.yourfirm.internal", api_key="...")
94
+ ```
95
+
96
+ Full documentation: [github.com/ebeirne/Lians](https://github.com/ebeirne/Lians)
@@ -0,0 +1,64 @@
1
+ """
2
+ Lians Python SDK — financial-grade AI memory with compliance built in.
3
+
4
+ Three clients, same API surface:
5
+
6
+ LiansClient — synchronous HTTP client (scripts, CLIs)
7
+ AsyncLiansClient — async HTTP client (FastAPI, async frameworks)
8
+ LocalLiansClient — zero-setup local SQLite mode (prototyping, CI)
9
+
10
+ Convenience methods on all clients::
11
+
12
+ client.add(agent_id, content, event_time, metadata=...)
13
+ client.add_from_messages(agent_id, messages=[{"role": "assistant", "content": "..."}])
14
+ client.recall(agent_id, query, k=5)
15
+ client.recall_at(agent_id, query, as_of=datetime(...)) # point-in-time / compliance
16
+ client.snapshot(agent_id, as_of=datetime(...)) # full knowledge state at T
17
+ client.backtest_check(agent_id, simulation_as_of=...) # lookahead-bias detection
18
+ client.erase(subject_id, request_ref) # GDPR crypto-shred
19
+
20
+ Framework integrations (optional extras)::
21
+
22
+ # LangChain (chat history + StructuredTools)
23
+ from lians.langchain_integration import LiansChatHistory, build_tools
24
+
25
+ # LangGraph (node factory functions)
26
+ from lians.langgraph_integration import create_recall_node, create_remember_node
27
+
28
+ # CrewAI (BaseTool wrappers)
29
+ from lians.crewai_integration import build_crewai_tools
30
+
31
+ # OpenAI Agents SDK (FunctionTool wrappers)
32
+ from lians.openai_agents_integration import build_openai_agent_tools
33
+
34
+ # AutoGen v0.4 (FunctionTool) / v0.2 (ConversableAgent)
35
+ from lians.autogen_integration import build_autogen_tools, build_autogen_functions
36
+
37
+ Install with extras::
38
+
39
+ pip install lians-sdk[langchain] # LangChain chat history + tools
40
+ pip install lians-sdk[langgraph] # LangGraph node factories
41
+ pip install lians-sdk[crewai] # CrewAI BaseTool wrappers
42
+ pip install lians-sdk[openai-agents] # OpenAI Agents SDK FunctionTools
43
+ pip install lians-sdk[autogen] # AutoGen v0.4 FunctionTools
44
+ pip install lians-sdk[local] # LocalLiansClient (SQLite)
45
+ pip install lians-sdk[all] # Everything
46
+ """
47
+ from .sync_client import LiansClient
48
+ from .client import AsyncLiansClient
49
+ from .local_client import LocalLiansClient
50
+
51
+ # Backward-compatibility aliases
52
+ AgentMemClient = LiansClient
53
+ AsyncAgentMemClient = AsyncLiansClient
54
+ LocalAgentMemClient = LocalLiansClient
55
+
56
+ __all__ = [
57
+ "LiansClient",
58
+ "AsyncLiansClient",
59
+ "LocalLiansClient",
60
+ # aliases
61
+ "AgentMemClient",
62
+ "AsyncAgentMemClient",
63
+ "LocalAgentMemClient",
64
+ ]
@@ -0,0 +1,287 @@
1
+ """
2
+ AutoGen v0.4 integration for Lians.
3
+
4
+ Provides function tools for AutoGen agents (autogen-agentchat >= 0.4 /
5
+ autogen-core >= 0.4). Works with both the ConversableAgent and the newer
6
+ AssistantAgent + function_tool pattern.
7
+
8
+ Install::
9
+
10
+ pip install lians[autogen]
11
+ # or: pip install autogen-agentchat autogen-core
12
+
13
+ Usage — AssistantAgent with function tools (AutoGen v0.4 async)::
14
+
15
+ from autogen_agentchat.agents import AssistantAgent
16
+ from autogen_ext.models import OpenAIChatCompletionClient
17
+ from lians import AsyncLiansClient
18
+ from lians.autogen_integration import build_autogen_tools
19
+
20
+ client = AsyncLiansClient(base_url="https://mem.firm.internal", api_key="...")
21
+ tools = build_autogen_tools(client, agent_id="equity-desk")
22
+
23
+ model_client = OpenAIChatCompletionClient(model="gpt-4o")
24
+ agent = AssistantAgent(
25
+ name="EquityAnalyst",
26
+ model_client=model_client,
27
+ tools=tools,
28
+ system_message="You are an equity analyst with persistent compliance-grade memory.",
29
+ )
30
+
31
+ Usage — ConversableAgent (AutoGen v0.2 / classic)::
32
+
33
+ from autogen import ConversableAgent
34
+ from lians import LocalLiansClient
35
+ from lians.autogen_integration import build_autogen_functions
36
+
37
+ client = LocalLiansClient()
38
+ functions, function_map = build_autogen_functions(client, agent_id="analyst")
39
+
40
+ agent = ConversableAgent(
41
+ name="analyst",
42
+ functions=functions,
43
+ function_map=function_map,
44
+ )
45
+
46
+ Three tools are returned by build_autogen_tools():
47
+
48
+ - ``agentmem_remember`` — store a fact with event timestamp and metadata
49
+ - ``agentmem_recall`` — retrieve current facts by semantic search
50
+ - ``agentmem_recall_at`` — retrieve facts valid at a specific past date (compliance)
51
+
52
+ The ``agentmem_recall_at`` tool supports AutoGen multi-agent compliance workflows:
53
+ "What did the risk-assessment agent know before the trade was placed?" — with a
54
+ tamper-evident SHA-256 audit chain, not a probabilistic reconstruction.
55
+ """
56
+ from __future__ import annotations
57
+
58
+ import asyncio
59
+ import json
60
+ from datetime import datetime
61
+ from typing import Any
62
+
63
+
64
+ def build_autogen_tools(client: Any, agent_id: str) -> list:
65
+ """
66
+ Return three AutoGen v0.4 FunctionTool instances for AssistantAgent.
67
+
68
+ Parameters
69
+ ----------
70
+ client:
71
+ Any Lians client — ``LocalLiansClient``, ``LiansClient``, or
72
+ ``AsyncLiansClient``. Async clients are detected automatically.
73
+ agent_id:
74
+ The agent namespace to read/write memories under.
75
+
76
+ Returns
77
+ -------
78
+ List of three AutoGen ``FunctionTool`` instances.
79
+
80
+ Raises
81
+ ------
82
+ ImportError
83
+ If ``autogen-core`` is not installed.
84
+ Install with: ``pip install lians[autogen]``
85
+ """
86
+ try:
87
+ from autogen_core.tools import FunctionTool # type: ignore[import]
88
+ except ImportError:
89
+ raise ImportError(
90
+ "autogen-core is required for AutoGen integration.\n"
91
+ "Install with: pip install lians[autogen]\n"
92
+ "or: pip install autogen-core"
93
+ )
94
+
95
+ _is_async = asyncio.iscoroutinefunction(getattr(client, "recall", None))
96
+
97
+ def _fmt(memories: list[dict]) -> str:
98
+ if not memories:
99
+ return "No relevant memories found."
100
+ return "\n".join(
101
+ f"[{(m.get('event_time') or '')[:10]}] {m.get('content') or '[erased]'}"
102
+ for m in memories
103
+ )
104
+
105
+ def _run_maybe_async(coro: Any) -> Any:
106
+ if _is_async:
107
+ return asyncio.get_event_loop().run_until_complete(coro)
108
+ return coro # already a plain value from sync client
109
+
110
+ # ── Tool functions ────────────────────────────────────────────────────────
111
+
112
+ async def agentmem_remember(
113
+ content: str,
114
+ event_time_iso: str,
115
+ metadata_json: str = "{}",
116
+ importance: float = 0.5,
117
+ ) -> str:
118
+ """
119
+ Store a fact in Lians persistent memory.
120
+
121
+ Use event_time_iso for when the event occurred (not now). Add structured
122
+ metadata for precision recall: ticker, metric, entity, source, jurisdiction.
123
+
124
+ Facts are AES-256-GCM encrypted at rest, written to a SHA-256 audit chain,
125
+ and automatically superseded when a newer value for the same entity+attribute
126
+ arrives — so recall always returns the current truth.
127
+
128
+ :param content: The fact or observation to store.
129
+ :param event_time_iso: ISO 8601 timestamp of when the event occurred.
130
+ Example: '2026-05-10T00:00:00Z'
131
+ :param metadata_json: JSON metadata tags.
132
+ Example: '{"ticker": "NVDA", "metric": "guidance"}'
133
+ :param importance: Salience 0.0–1.0. Default 0.5.
134
+ """
135
+ dt = datetime.fromisoformat(event_time_iso.replace("Z", "+00:00"))
136
+ meta = json.loads(metadata_json) if isinstance(metadata_json, str) else {}
137
+ kwargs: dict[str, Any] = dict(
138
+ agent_id=agent_id,
139
+ content=content,
140
+ event_time=dt,
141
+ metadata=meta,
142
+ importance=importance,
143
+ source="autogen",
144
+ )
145
+ if _is_async:
146
+ await client.add(**kwargs)
147
+ else:
148
+ client.add(**kwargs)
149
+ return f"Stored: {content[:120]}{'…' if len(content) > 120 else ''}"
150
+
151
+ async def agentmem_recall(query: str, k: int = 5) -> str:
152
+ """
153
+ Retrieve current relevant facts from Lians.
154
+
155
+ Superseded facts are excluded at the DB layer. Only the most recent
156
+ valid value for each fact is returned — your agent never sees stale context.
157
+
158
+ :param query: Natural-language query. Example: 'NVDA guidance FY2026'
159
+ :param k: Number of memories to return (1–20). Default 5.
160
+ """
161
+ if _is_async:
162
+ result = await client.recall(agent_id=agent_id, query=query, k=k)
163
+ else:
164
+ result = client.recall(agent_id=agent_id, query=query, k=k)
165
+ return _fmt(result.get("memories", []))
166
+
167
+ async def agentmem_recall_at(query: str, as_of_iso: str, k: int = 5) -> str:
168
+ """
169
+ Retrieve facts valid at a specific point in time (compliance/audit path).
170
+
171
+ Returns the exact knowledge state at the given timestamp — supports
172
+ out-of-order ingestion correctly. Use in multi-agent workflows where one
173
+ agent must reconstruct what another agent knew before a decision.
174
+
175
+ :param query: Natural-language query.
176
+ :param as_of_iso: ISO 8601 timestamp. Only facts valid at this moment
177
+ are returned. Example: '2026-03-01T00:00:00Z'
178
+ :param k: Number of memories to return (1–20). Default 5.
179
+ """
180
+ as_of = datetime.fromisoformat(as_of_iso.replace("Z", "+00:00"))
181
+ if _is_async:
182
+ result = await client.recall(agent_id=agent_id, query=query, k=k, as_of=as_of)
183
+ else:
184
+ result = client.recall(agent_id=agent_id, query=query, k=k, as_of=as_of)
185
+ return f"Facts valid as of {as_of_iso[:10]}:\n{_fmt(result.get('memories', []))}"
186
+
187
+ return [
188
+ FunctionTool(agentmem_remember, description=agentmem_remember.__doc__ or ""),
189
+ FunctionTool(agentmem_recall, description=agentmem_recall.__doc__ or ""),
190
+ FunctionTool(agentmem_recall_at, description=agentmem_recall_at.__doc__ or ""),
191
+ ]
192
+
193
+
194
+ def build_autogen_functions(
195
+ client: Any,
196
+ agent_id: str,
197
+ ) -> tuple[list[dict], dict[str, Any]]:
198
+ """
199
+ Return (functions_schema, function_map) for AutoGen v0.2 ConversableAgent.
200
+
201
+ The functions_schema list goes into the ``functions`` parameter; the
202
+ function_map dict goes into ``function_map``.
203
+
204
+ Parameters
205
+ ----------
206
+ client:
207
+ Any synchronous Lians client (LocalLiansClient or LiansClient).
208
+ agent_id:
209
+ The agent namespace to read/write memories under.
210
+
211
+ Returns
212
+ -------
213
+ A (list, dict) tuple compatible with ConversableAgent's ``functions`` and
214
+ ``function_map`` parameters.
215
+ """
216
+ def _fmt(memories: list[dict]) -> str:
217
+ if not memories:
218
+ return "No relevant memories found."
219
+ return "\n".join(
220
+ f"[{(m.get('event_time') or '')[:10]}] {m.get('content') or '[erased]'}"
221
+ for m in memories
222
+ )
223
+
224
+ def _remember(content: str, event_time_iso: str, metadata_json: str = "{}", importance: float = 0.5) -> str:
225
+ dt = datetime.fromisoformat(event_time_iso.replace("Z", "+00:00"))
226
+ meta = json.loads(metadata_json) if isinstance(metadata_json, str) else {}
227
+ client.add(agent_id=agent_id, content=content, event_time=dt, metadata=meta, importance=importance, source="autogen_v2")
228
+ return f"Stored: {content[:120]}"
229
+
230
+ def _recall(query: str, k: int = 5) -> str:
231
+ result = client.recall(agent_id=agent_id, query=query, k=k)
232
+ return _fmt(result.get("memories", []))
233
+
234
+ def _recall_at(query: str, as_of_iso: str, k: int = 5) -> str:
235
+ as_of = datetime.fromisoformat(as_of_iso.replace("Z", "+00:00"))
236
+ result = client.recall(agent_id=agent_id, query=query, k=k, as_of=as_of)
237
+ return f"Facts valid as of {as_of_iso[:10]}:\n{_fmt(result.get('memories', []))}"
238
+
239
+ functions = [
240
+ {
241
+ "name": "agentmem_remember",
242
+ "description": "Store a fact with its event timestamp in Lians persistent memory.",
243
+ "parameters": {
244
+ "type": "object",
245
+ "properties": {
246
+ "content": {"type": "string", "description": "The fact to remember."},
247
+ "event_time_iso": {"type": "string", "description": "ISO 8601 event timestamp."},
248
+ "metadata_json": {"type": "string", "description": "JSON metadata tags.", "default": "{}"},
249
+ "importance": {"type": "number", "description": "Salience 0–1.", "default": 0.5},
250
+ },
251
+ "required": ["content", "event_time_iso"],
252
+ },
253
+ },
254
+ {
255
+ "name": "agentmem_recall",
256
+ "description": "Retrieve current relevant facts from Lians (superseded facts excluded).",
257
+ "parameters": {
258
+ "type": "object",
259
+ "properties": {
260
+ "query": {"type": "string"},
261
+ "k": {"type": "integer", "default": 5},
262
+ },
263
+ "required": ["query"],
264
+ },
265
+ },
266
+ {
267
+ "name": "agentmem_recall_at",
268
+ "description": "Retrieve facts valid at a specific timestamp (compliance / audit path).",
269
+ "parameters": {
270
+ "type": "object",
271
+ "properties": {
272
+ "query": {"type": "string"},
273
+ "as_of_iso": {"type": "string", "description": "ISO 8601 timestamp."},
274
+ "k": {"type": "integer", "default": 5},
275
+ },
276
+ "required": ["query", "as_of_iso"],
277
+ },
278
+ },
279
+ ]
280
+
281
+ function_map = {
282
+ "agentmem_remember": _remember,
283
+ "agentmem_recall": _recall,
284
+ "agentmem_recall_at": _recall_at,
285
+ }
286
+
287
+ return functions, function_map