abstractagent 0.2.0__py3-none-any.whl → 0.3.1__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.
- abstractagent/adapters/__init__.py +2 -1
- abstractagent/adapters/codeact_runtime.py +907 -60
- abstractagent/adapters/generation_params.py +82 -0
- abstractagent/adapters/media.py +45 -0
- abstractagent/adapters/memact_runtime.py +959 -0
- abstractagent/adapters/react_runtime.py +1357 -135
- abstractagent/agents/__init__.py +4 -0
- abstractagent/agents/base.py +89 -1
- abstractagent/agents/codeact.py +125 -18
- abstractagent/agents/memact.py +280 -0
- abstractagent/agents/react.py +129 -18
- abstractagent/logic/__init__.py +2 -0
- abstractagent/logic/builtins.py +270 -5
- abstractagent/logic/codeact.py +91 -81
- abstractagent/logic/memact.py +128 -0
- abstractagent/logic/react.py +91 -50
- abstractagent/repl.py +24 -447
- abstractagent/scripts/__init__.py +5 -0
- abstractagent/scripts/lmstudio_tool_eval.py +426 -0
- abstractagent/tools/__init__.py +9 -0
- abstractagent-0.3.1.dist-info/METADATA +112 -0
- abstractagent-0.3.1.dist-info/RECORD +33 -0
- {abstractagent-0.2.0.dist-info → abstractagent-0.3.1.dist-info}/WHEEL +1 -1
- abstractagent/ui/__init__.py +0 -5
- abstractagent/ui/question.py +0 -197
- abstractagent-0.2.0.dist-info/METADATA +0 -134
- abstractagent-0.2.0.dist-info/RECORD +0 -28
- {abstractagent-0.2.0.dist-info → abstractagent-0.3.1.dist-info}/entry_points.txt +0 -0
- {abstractagent-0.2.0.dist-info → abstractagent-0.3.1.dist-info}/licenses/LICENSE +0 -0
- {abstractagent-0.2.0.dist-info → abstractagent-0.3.1.dist-info}/top_level.txt +0 -0
abstractagent/agents/react.py
CHANGED
|
@@ -15,11 +15,20 @@ from __future__ import annotations
|
|
|
15
15
|
from typing import Any, Callable, Dict, List, Optional
|
|
16
16
|
|
|
17
17
|
from abstractcore.tools import ToolDefinition
|
|
18
|
-
from abstractruntime import RunState, Runtime, WorkflowSpec
|
|
18
|
+
from abstractruntime import RunState, RunStatus, Runtime, WorkflowSpec
|
|
19
19
|
|
|
20
20
|
from .base import BaseAgent
|
|
21
21
|
from ..adapters.react_runtime import create_react_workflow
|
|
22
|
-
from ..logic.builtins import
|
|
22
|
+
from ..logic.builtins import (
|
|
23
|
+
ASK_USER_TOOL,
|
|
24
|
+
COMPACT_MEMORY_TOOL,
|
|
25
|
+
DELEGATE_AGENT_TOOL,
|
|
26
|
+
INSPECT_VARS_TOOL,
|
|
27
|
+
OPEN_ATTACHMENT_TOOL,
|
|
28
|
+
RECALL_MEMORY_TOOL,
|
|
29
|
+
REMEMBER_TOOL,
|
|
30
|
+
REMEMBER_NOTE_TOOL,
|
|
31
|
+
)
|
|
23
32
|
from ..logic.react import ReActLogic
|
|
24
33
|
|
|
25
34
|
|
|
@@ -54,7 +63,10 @@ class ReactAgent(BaseAgent):
|
|
|
54
63
|
on_step: Optional[Callable[[str, Dict[str, Any]], None]] = None,
|
|
55
64
|
max_iterations: int = 25,
|
|
56
65
|
max_history_messages: int = -1,
|
|
57
|
-
max_tokens: Optional[int] =
|
|
66
|
+
max_tokens: Optional[int] = None,
|
|
67
|
+
plan_mode: bool = False,
|
|
68
|
+
review_mode: bool = True,
|
|
69
|
+
review_max_rounds: int = 3,
|
|
58
70
|
actor_id: Optional[str] = None,
|
|
59
71
|
session_id: Optional[str] = None,
|
|
60
72
|
):
|
|
@@ -66,6 +78,11 @@ class ReactAgent(BaseAgent):
|
|
|
66
78
|
if self._max_history_messages != -1 and self._max_history_messages < 1:
|
|
67
79
|
self._max_history_messages = 1
|
|
68
80
|
self._max_tokens = max_tokens
|
|
81
|
+
self._plan_mode = bool(plan_mode)
|
|
82
|
+
self._review_mode = bool(review_mode)
|
|
83
|
+
self._review_max_rounds = int(review_max_rounds)
|
|
84
|
+
if self._review_max_rounds < 0:
|
|
85
|
+
self._review_max_rounds = 0
|
|
69
86
|
|
|
70
87
|
self.logic: Optional[ReActLogic] = None
|
|
71
88
|
super().__init__(
|
|
@@ -79,7 +96,17 @@ class ReactAgent(BaseAgent):
|
|
|
79
96
|
def _create_workflow(self) -> WorkflowSpec:
|
|
80
97
|
tool_defs = _tool_definitions_from_callables(self.tools)
|
|
81
98
|
# Built-in ask_user is a schema-only tool (handled via ASK_USER effect in the adapter).
|
|
82
|
-
tool_defs = [
|
|
99
|
+
tool_defs = [
|
|
100
|
+
ASK_USER_TOOL,
|
|
101
|
+
OPEN_ATTACHMENT_TOOL,
|
|
102
|
+
RECALL_MEMORY_TOOL,
|
|
103
|
+
INSPECT_VARS_TOOL,
|
|
104
|
+
REMEMBER_TOOL,
|
|
105
|
+
REMEMBER_NOTE_TOOL,
|
|
106
|
+
COMPACT_MEMORY_TOOL,
|
|
107
|
+
DELEGATE_AGENT_TOOL,
|
|
108
|
+
*tool_defs,
|
|
109
|
+
]
|
|
83
110
|
|
|
84
111
|
logic = ReActLogic(
|
|
85
112
|
tools=tool_defs,
|
|
@@ -89,27 +116,103 @@ class ReactAgent(BaseAgent):
|
|
|
89
116
|
self.logic = logic
|
|
90
117
|
return create_react_workflow(logic=logic, on_step=self.on_step)
|
|
91
118
|
|
|
92
|
-
def start(
|
|
119
|
+
def start(
|
|
120
|
+
self,
|
|
121
|
+
task: str,
|
|
122
|
+
*,
|
|
123
|
+
plan_mode: Optional[bool] = None,
|
|
124
|
+
review_mode: Optional[bool] = None,
|
|
125
|
+
review_max_rounds: Optional[int] = None,
|
|
126
|
+
allowed_tools: Optional[List[str]] = None,
|
|
127
|
+
temperature: Optional[float] = None,
|
|
128
|
+
seed: Optional[int] = None,
|
|
129
|
+
attachments: Optional[List[Any]] = None,
|
|
130
|
+
) -> str:
|
|
93
131
|
task = str(task or "").strip()
|
|
94
132
|
if not task:
|
|
95
133
|
raise ValueError("task must be a non-empty string")
|
|
96
134
|
|
|
135
|
+
eff_plan_mode = self._plan_mode if plan_mode is None else bool(plan_mode)
|
|
136
|
+
eff_review_mode = self._review_mode if review_mode is None else bool(review_mode)
|
|
137
|
+
eff_review_max_rounds = self._review_max_rounds if review_max_rounds is None else int(review_max_rounds)
|
|
138
|
+
if eff_review_max_rounds < 0:
|
|
139
|
+
eff_review_max_rounds = 0
|
|
140
|
+
|
|
141
|
+
# Base limits come from the Runtime config so model capabilities (max context)
|
|
142
|
+
# are respected by default, unless explicitly overridden by the agent/session.
|
|
143
|
+
try:
|
|
144
|
+
base_limits = dict(self.runtime.config.to_limits_dict())
|
|
145
|
+
except Exception:
|
|
146
|
+
base_limits = {}
|
|
147
|
+
limits: Dict[str, Any] = dict(base_limits)
|
|
148
|
+
limits.setdefault("warn_iterations_pct", 80)
|
|
149
|
+
limits.setdefault("warn_tokens_pct", 80)
|
|
150
|
+
limits["max_iterations"] = int(self._max_iterations)
|
|
151
|
+
limits["current_iteration"] = 0
|
|
152
|
+
limits["max_history_messages"] = int(self._max_history_messages)
|
|
153
|
+
# Message-size guards for LLM-visible context (character-level).
|
|
154
|
+
# These are applied when building the provider payload; the durable run history
|
|
155
|
+
# still preserves full message text.
|
|
156
|
+
# Disabled by default (-1): enable by setting a positive character budget.
|
|
157
|
+
limits.setdefault("max_message_chars", -1)
|
|
158
|
+
limits.setdefault("max_tool_message_chars", -1)
|
|
159
|
+
limits["estimated_tokens_used"] = 0
|
|
160
|
+
# ReAct output-token capping is controlled via `_limits.max_output_tokens`.
|
|
161
|
+
# Policy: unset by default (None) to avoid artificial truncation.
|
|
162
|
+
try:
|
|
163
|
+
max_output_tokens_override = int(self._max_tokens) if self._max_tokens is not None else None
|
|
164
|
+
except Exception:
|
|
165
|
+
max_output_tokens_override = None
|
|
166
|
+
if isinstance(max_output_tokens_override, int) and max_output_tokens_override > 0:
|
|
167
|
+
limits["max_output_tokens"] = max_output_tokens_override
|
|
168
|
+
else:
|
|
169
|
+
limits.setdefault("max_output_tokens", None)
|
|
170
|
+
|
|
97
171
|
vars: Dict[str, Any] = {
|
|
98
172
|
"context": {"task": task, "messages": _copy_messages(self.session_messages)},
|
|
99
173
|
"scratchpad": {"iteration": 0, "max_iterations": int(self._max_iterations)},
|
|
100
|
-
"_runtime": {
|
|
174
|
+
"_runtime": {
|
|
175
|
+
"inbox": [],
|
|
176
|
+
"plan_mode": eff_plan_mode,
|
|
177
|
+
"review_mode": eff_review_mode,
|
|
178
|
+
"review_max_rounds": eff_review_max_rounds,
|
|
179
|
+
},
|
|
101
180
|
"_temp": {},
|
|
102
181
|
# Canonical _limits namespace for runtime awareness
|
|
103
|
-
"_limits":
|
|
104
|
-
"max_iterations": int(self._max_iterations),
|
|
105
|
-
"current_iteration": 0,
|
|
106
|
-
"max_tokens": self._max_tokens,
|
|
107
|
-
"max_history_messages": int(self._max_history_messages),
|
|
108
|
-
"estimated_tokens_used": 0,
|
|
109
|
-
"warn_iterations_pct": 80,
|
|
110
|
-
"warn_tokens_pct": 80,
|
|
111
|
-
},
|
|
182
|
+
"_limits": limits,
|
|
112
183
|
}
|
|
184
|
+
if attachments:
|
|
185
|
+
items: list[Any]
|
|
186
|
+
if isinstance(attachments, tuple):
|
|
187
|
+
items = list(attachments)
|
|
188
|
+
else:
|
|
189
|
+
items = attachments if isinstance(attachments, list) else []
|
|
190
|
+
normalized: list[Any] = []
|
|
191
|
+
for item in items:
|
|
192
|
+
if isinstance(item, str) and item.strip():
|
|
193
|
+
normalized.append(item.strip())
|
|
194
|
+
continue
|
|
195
|
+
if isinstance(item, dict):
|
|
196
|
+
aid = item.get("$artifact")
|
|
197
|
+
if not (isinstance(aid, str) and aid.strip()):
|
|
198
|
+
aid = item.get("artifact_id")
|
|
199
|
+
if isinstance(aid, str) and aid.strip():
|
|
200
|
+
normalized.append(dict(item))
|
|
201
|
+
if normalized:
|
|
202
|
+
vars["context"]["attachments"] = normalized
|
|
203
|
+
if temperature is not None:
|
|
204
|
+
try:
|
|
205
|
+
vars["_runtime"]["temperature"] = float(temperature)
|
|
206
|
+
except Exception:
|
|
207
|
+
pass
|
|
208
|
+
if seed is not None:
|
|
209
|
+
try:
|
|
210
|
+
vars["_runtime"]["seed"] = int(seed)
|
|
211
|
+
except Exception:
|
|
212
|
+
pass
|
|
213
|
+
if isinstance(allowed_tools, list):
|
|
214
|
+
normalized = [str(t).strip() for t in allowed_tools if isinstance(t, str) and t.strip()]
|
|
215
|
+
vars["_runtime"]["allowed_tools"] = normalized
|
|
113
216
|
|
|
114
217
|
run_id = self.runtime.start(
|
|
115
218
|
workflow=self.workflow,
|
|
@@ -154,7 +257,10 @@ class ReactAgent(BaseAgent):
|
|
|
154
257
|
def step(self) -> RunState:
|
|
155
258
|
if not self._current_run_id:
|
|
156
259
|
raise RuntimeError("No active run. Call start() first.")
|
|
157
|
-
|
|
260
|
+
state = self.runtime.tick(workflow=self.workflow, run_id=self._current_run_id, max_steps=1)
|
|
261
|
+
if state.status in (RunStatus.COMPLETED, RunStatus.FAILED, RunStatus.CANCELLED):
|
|
262
|
+
self._sync_session_caches_from_state(state)
|
|
263
|
+
return state
|
|
158
264
|
|
|
159
265
|
|
|
160
266
|
def create_react_agent(
|
|
@@ -165,7 +271,10 @@ def create_react_agent(
|
|
|
165
271
|
on_step: Optional[Callable[[str, Dict[str, Any]], None]] = None,
|
|
166
272
|
max_iterations: int = 25,
|
|
167
273
|
max_history_messages: int = -1,
|
|
168
|
-
max_tokens: Optional[int] =
|
|
274
|
+
max_tokens: Optional[int] = None,
|
|
275
|
+
plan_mode: bool = False,
|
|
276
|
+
review_mode: bool = True,
|
|
277
|
+
review_max_rounds: int = 3,
|
|
169
278
|
llm_kwargs: Optional[Dict[str, Any]] = None,
|
|
170
279
|
run_store: Optional[Any] = None,
|
|
171
280
|
ledger_store: Optional[Any] = None,
|
|
@@ -197,6 +306,9 @@ def create_react_agent(
|
|
|
197
306
|
max_iterations=max_iterations,
|
|
198
307
|
max_history_messages=max_history_messages,
|
|
199
308
|
max_tokens=max_tokens,
|
|
309
|
+
plan_mode=plan_mode,
|
|
310
|
+
review_mode=review_mode,
|
|
311
|
+
review_max_rounds=review_max_rounds,
|
|
200
312
|
actor_id=actor_id,
|
|
201
313
|
session_id=session_id,
|
|
202
314
|
)
|
|
@@ -207,4 +319,3 @@ __all__ = [
|
|
|
207
319
|
"create_react_workflow",
|
|
208
320
|
"create_react_agent",
|
|
209
321
|
]
|
|
210
|
-
|
abstractagent/logic/__init__.py
CHANGED
|
@@ -6,6 +6,7 @@ workflow wiring lives under `abstractagent.adapters`.
|
|
|
6
6
|
|
|
7
7
|
from .builtins import ASK_USER_TOOL
|
|
8
8
|
from .codeact import CodeActLogic
|
|
9
|
+
from .memact import MemActLogic
|
|
9
10
|
from .react import ReActLogic
|
|
10
11
|
from .types import AskUserAction, FinalAnswer, LLMRequest
|
|
11
12
|
|
|
@@ -16,4 +17,5 @@ __all__ = [
|
|
|
16
17
|
"FinalAnswer",
|
|
17
18
|
"ReActLogic",
|
|
18
19
|
"CodeActLogic",
|
|
20
|
+
"MemActLogic",
|
|
19
21
|
]
|
abstractagent/logic/builtins.py
CHANGED
|
@@ -9,10 +9,7 @@ from abstractcore.tools import ToolDefinition
|
|
|
9
9
|
|
|
10
10
|
ASK_USER_TOOL = ToolDefinition(
|
|
11
11
|
name="ask_user",
|
|
12
|
-
description=
|
|
13
|
-
"Ask the user a question when you need clarification or input. "
|
|
14
|
-
"Use this when the task is ambiguous or you need the user to make a choice."
|
|
15
|
-
),
|
|
12
|
+
description="Ask the user a question.",
|
|
16
13
|
parameters={
|
|
17
14
|
"question": {
|
|
18
15
|
"type": "string",
|
|
@@ -22,8 +19,276 @@ ASK_USER_TOOL = ToolDefinition(
|
|
|
22
19
|
"type": "array",
|
|
23
20
|
"items": {"type": "string"},
|
|
24
21
|
"description": "Optional list of choices for the user to pick from",
|
|
22
|
+
"default": None,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
when_to_use="Use when the task is ambiguous or you need user input to proceed.",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
OPEN_ATTACHMENT_TOOL = ToolDefinition(
|
|
29
|
+
name="open_attachment",
|
|
30
|
+
description="Read an attachment (artifact) from the current session with bounded output.",
|
|
31
|
+
parameters={
|
|
32
|
+
"artifact_id": {"type": "string", "description": "Attachment artifact id (preferred).", "default": None},
|
|
33
|
+
"handle": {"type": "string", "description": "Attachment handle (usually '@path').", "default": None},
|
|
34
|
+
"expected_sha256": {"type": "string", "description": "Optional sha256 to disambiguate versions.", "default": None},
|
|
35
|
+
"start_line": {"type": "integer", "description": "1-based start line (default 1).", "default": 1},
|
|
36
|
+
"end_line": {"type": "integer", "description": "Optional end line (inclusive).", "default": None},
|
|
37
|
+
"max_chars": {"type": "integer", "description": "Maximum characters to return (default 8000).", "default": 8000},
|
|
38
|
+
},
|
|
39
|
+
when_to_use=(
|
|
40
|
+
"Use only to open stored (non-active) session attachments or to fetch a bounded, line-numbered excerpt when the "
|
|
41
|
+
"attachment is not already provided in this call. Prefer artifact_id when available; otherwise use handle."
|
|
42
|
+
),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
RECALL_MEMORY_TOOL = ToolDefinition(
|
|
46
|
+
name="recall_memory",
|
|
47
|
+
description="Recall archived memory spans with provenance (by span_id/query/tags/time range).",
|
|
48
|
+
parameters={
|
|
49
|
+
"span_id": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"description": (
|
|
52
|
+
"Optional span identifier (artifact id) or 1-based index into archived spans. "
|
|
53
|
+
"If a summary includes span_id=..., use that exact value."
|
|
54
|
+
),
|
|
55
|
+
"default": None,
|
|
56
|
+
},
|
|
57
|
+
"query": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "Optional keyword query (topic/person/etc). Performs metadata-first search with bounded deep scan over archived messages.",
|
|
60
|
+
"default": None,
|
|
61
|
+
},
|
|
62
|
+
"since": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"description": "Optional ISO8601 start timestamp for time-range filtering.",
|
|
65
|
+
"default": None,
|
|
66
|
+
},
|
|
67
|
+
"until": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"description": "Optional ISO8601 end timestamp for time-range filtering.",
|
|
70
|
+
"default": None,
|
|
71
|
+
},
|
|
72
|
+
"tags": {
|
|
73
|
+
"type": "object",
|
|
74
|
+
"description": (
|
|
75
|
+
"Optional metadata tag filters.\n"
|
|
76
|
+
"- Values may be a string or a list of strings.\n"
|
|
77
|
+
"- Example: {\"topic\":\"api\",\"person\":[\"alice\",\"bob\"]}\n"
|
|
78
|
+
"Use tags_mode to control AND/OR across tag keys."
|
|
79
|
+
),
|
|
80
|
+
"default": None,
|
|
81
|
+
},
|
|
82
|
+
"tags_mode": {
|
|
83
|
+
"type": "string",
|
|
84
|
+
"description": (
|
|
85
|
+
"How to combine tag keys: all (AND across keys) | any (OR across keys). "
|
|
86
|
+
"Within a key, list values are treated as OR."
|
|
87
|
+
),
|
|
88
|
+
"default": "all",
|
|
89
|
+
},
|
|
90
|
+
"usernames": {
|
|
91
|
+
"type": "array",
|
|
92
|
+
"items": {"type": "string"},
|
|
93
|
+
"description": (
|
|
94
|
+
"Optional author filter (actor ids / usernames). Matches spans created_by case-insensitively. "
|
|
95
|
+
"Semantics: OR (any listed author)."
|
|
96
|
+
),
|
|
97
|
+
"default": None,
|
|
98
|
+
},
|
|
99
|
+
"locations": {
|
|
100
|
+
"type": "array",
|
|
101
|
+
"items": {"type": "string"},
|
|
102
|
+
"description": (
|
|
103
|
+
"Optional location filter. Matches spans by explicit location metadata (or tags.location). "
|
|
104
|
+
"Semantics: OR (any listed location)."
|
|
105
|
+
),
|
|
106
|
+
"default": None,
|
|
107
|
+
},
|
|
108
|
+
"limit_spans": {
|
|
109
|
+
"type": "integer",
|
|
110
|
+
"description": "Maximum number of spans to return (default 5).",
|
|
111
|
+
"default": 5,
|
|
112
|
+
},
|
|
113
|
+
"connected": {
|
|
114
|
+
"type": "boolean",
|
|
115
|
+
"description": "If true, also include connected spans (time neighbors and shared-tag neighbors).",
|
|
116
|
+
"default": False,
|
|
117
|
+
},
|
|
118
|
+
"neighbor_hops": {
|
|
119
|
+
"type": "integer",
|
|
120
|
+
"description": "When connected=true, include up to this many neighbor spans on each side (default 1).",
|
|
121
|
+
"default": 1,
|
|
122
|
+
},
|
|
123
|
+
"max_messages": {
|
|
124
|
+
"type": "integer",
|
|
125
|
+
"description": "Maximum total messages to render in the recall output across all spans (-1 = no truncation).",
|
|
126
|
+
"default": -1,
|
|
127
|
+
},
|
|
128
|
+
"scope": {
|
|
129
|
+
"type": "string",
|
|
130
|
+
"description": "Memory scope to query: run | session | global | all (default run).",
|
|
131
|
+
"default": "run",
|
|
132
|
+
},
|
|
133
|
+
"recall_level": {
|
|
134
|
+
"type": "string",
|
|
135
|
+
"enum": ["urgent", "standard", "deep"],
|
|
136
|
+
"description": (
|
|
137
|
+
"Optional recall effort policy.\n"
|
|
138
|
+
"- urgent: fastest, tight budgets\n"
|
|
139
|
+
"- standard: bounded but more thorough\n"
|
|
140
|
+
"- deep: may be slow/expensive\n"
|
|
141
|
+
"No silent downgrade: budgets/permissions are enforced by the runtime."
|
|
142
|
+
),
|
|
143
|
+
"default": None,
|
|
25
144
|
},
|
|
26
145
|
},
|
|
27
|
-
when_to_use="
|
|
146
|
+
when_to_use="Use after compaction or when you need exact details from earlier context.",
|
|
28
147
|
)
|
|
29
148
|
|
|
149
|
+
INSPECT_VARS_TOOL = ToolDefinition(
|
|
150
|
+
name="inspect_vars",
|
|
151
|
+
description="Inspect durable run-state variables by path (e.g., scratchpad/runtime vars).",
|
|
152
|
+
parameters={
|
|
153
|
+
"path": {
|
|
154
|
+
"type": "string",
|
|
155
|
+
"description": (
|
|
156
|
+
"Path to inspect (default 'scratchpad'). Supports dot paths like 'scratchpad.foo[0]' "
|
|
157
|
+
"or JSON pointer paths like '/scratchpad/foo/0'."
|
|
158
|
+
),
|
|
159
|
+
"default": "scratchpad",
|
|
160
|
+
},
|
|
161
|
+
"keys_only": {
|
|
162
|
+
"type": "boolean",
|
|
163
|
+
"description": "If true, return keys/length instead of the full value (useful to navigate large objects).",
|
|
164
|
+
"default": False,
|
|
165
|
+
},
|
|
166
|
+
"target_run_id": {
|
|
167
|
+
"type": "string",
|
|
168
|
+
"description": "Optional run id to inspect (defaults to the current run).",
|
|
169
|
+
"default": None,
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
when_to_use=(
|
|
173
|
+
"Use to debug or inspect scratchpad/runtime vars (prefer keys_only=true first)."
|
|
174
|
+
),
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
REMEMBER_TOOL = ToolDefinition(
|
|
178
|
+
name="remember",
|
|
179
|
+
description="Tag an archived memory span for later recall.",
|
|
180
|
+
parameters={
|
|
181
|
+
"span_id": {
|
|
182
|
+
"type": "string",
|
|
183
|
+
"description": (
|
|
184
|
+
"Span identifier (artifact id) or 1-based index into archived spans. "
|
|
185
|
+
"If a summary includes span_id=..., use that exact value."
|
|
186
|
+
),
|
|
187
|
+
},
|
|
188
|
+
"tags": {
|
|
189
|
+
"type": "object",
|
|
190
|
+
"description": (
|
|
191
|
+
"Tags to set on the span (JSON-safe dict[str,str]), e.g. {\"topic\":\"api\",\"person\":\"alice\"}. "
|
|
192
|
+
"At least one tag is required."
|
|
193
|
+
),
|
|
194
|
+
},
|
|
195
|
+
"merge": {
|
|
196
|
+
"type": "boolean",
|
|
197
|
+
"description": "If true (default), merges tags into existing tags. If false, replaces existing tags.",
|
|
198
|
+
"default": True,
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
when_to_use=(
|
|
202
|
+
"Use when you want to label a recalled/compacted span with durable tags."
|
|
203
|
+
),
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
REMEMBER_NOTE_TOOL = ToolDefinition(
|
|
207
|
+
name="remember_note",
|
|
208
|
+
description="Store a durable memory note (decision/fact) with optional tags and sources.",
|
|
209
|
+
parameters={
|
|
210
|
+
"note": {
|
|
211
|
+
"type": "string",
|
|
212
|
+
"description": "The note to remember (required). Keep it short and specific.",
|
|
213
|
+
},
|
|
214
|
+
"tags": {
|
|
215
|
+
"type": "object",
|
|
216
|
+
"description": "Optional tags (dict[str,str]) to help recall later, e.g. {\"topic\":\"api\",\"person\":\"alice\"}.",
|
|
217
|
+
"default": None,
|
|
218
|
+
},
|
|
219
|
+
"sources": {
|
|
220
|
+
"type": "object",
|
|
221
|
+
"description": (
|
|
222
|
+
"Optional provenance sources for this note. Use span_ids/message_ids when available.\n"
|
|
223
|
+
"Example: {\"span_ids\":[\"span_...\"], \"message_ids\":[\"msg_...\"]}"
|
|
224
|
+
),
|
|
225
|
+
"default": None,
|
|
226
|
+
},
|
|
227
|
+
"location": {
|
|
228
|
+
"type": "string",
|
|
229
|
+
"description": "Optional location for this memory note (user perspective).",
|
|
230
|
+
"default": None,
|
|
231
|
+
},
|
|
232
|
+
"scope": {
|
|
233
|
+
"type": "string",
|
|
234
|
+
"description": "Where to store this note: run | session | global (default run).",
|
|
235
|
+
"default": "run",
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
when_to_use=(
|
|
239
|
+
"When you want to persist a key insight/decision/fact for later recall by time/topic/person, "
|
|
240
|
+
"especially before any compaction span exists."
|
|
241
|
+
),
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
COMPACT_MEMORY_TOOL = ToolDefinition(
|
|
245
|
+
name="compact_memory",
|
|
246
|
+
description="Compact older conversation context into an archived span and insert a summary handle.",
|
|
247
|
+
parameters={
|
|
248
|
+
"preserve_recent": {
|
|
249
|
+
"type": "integer",
|
|
250
|
+
"description": "Number of most recent non-system messages to keep verbatim (default 6).",
|
|
251
|
+
"default": 6,
|
|
252
|
+
},
|
|
253
|
+
"compression_mode": {
|
|
254
|
+
"type": "string",
|
|
255
|
+
"description": "Compression mode: light | standard | heavy (default standard).",
|
|
256
|
+
"default": "standard",
|
|
257
|
+
},
|
|
258
|
+
"focus": {
|
|
259
|
+
"type": "string",
|
|
260
|
+
"description": "Optional focus/topic to prioritize in the summary.",
|
|
261
|
+
"default": None,
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
when_to_use="Use when the active context is too large and you need to reduce it while keeping provenance.",
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
DELEGATE_AGENT_TOOL = ToolDefinition(
|
|
268
|
+
name="delegate_agent",
|
|
269
|
+
description="Delegate a subtask to a fresh agent run with smaller context and restricted tools.",
|
|
270
|
+
parameters={
|
|
271
|
+
"task": {
|
|
272
|
+
"type": "string",
|
|
273
|
+
"description": "The delegated task (required). Keep it specific and self-contained.",
|
|
274
|
+
},
|
|
275
|
+
"context": {
|
|
276
|
+
"type": "string",
|
|
277
|
+
"description": "Minimal supporting context for the delegated task (optional).",
|
|
278
|
+
"default": "",
|
|
279
|
+
},
|
|
280
|
+
"tools": {
|
|
281
|
+
"type": "array",
|
|
282
|
+
"items": {"type": "string"},
|
|
283
|
+
"description": (
|
|
284
|
+
"Tool allowlist for the delegated agent (optional). "
|
|
285
|
+
"When omitted, the delegated agent inherits the current allowlist."
|
|
286
|
+
),
|
|
287
|
+
"default": None,
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
when_to_use=(
|
|
291
|
+
"Use when you can split off a subtask that can be completed with a small context (e.g., "
|
|
292
|
+
"inspect a few files, search for specific symbols, summarize findings)."
|
|
293
|
+
),
|
|
294
|
+
)
|