agentx-dev 2.4__tar.gz → 3.0.1__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.
- agentx_dev-3.0.1/AGENTX.md +308 -0
- agentx_dev-3.0.1/LICENSE +21 -0
- agentx_dev-3.0.1/MANIFEST.in +11 -0
- agentx_dev-3.0.1/PKG-INFO +886 -0
- agentx_dev-3.0.1/README.md +835 -0
- agentx_dev-3.0.1/agentx_dev/Agents/Agent.py +402 -0
- agentx_dev-3.0.1/agentx_dev/AsyncTools.py +160 -0
- agentx_dev-3.0.1/agentx_dev/AutoSetup.py +164 -0
- agentx_dev-3.0.1/agentx_dev/Cache.py +471 -0
- agentx_dev-3.0.1/agentx_dev/ChatModel.py +1174 -0
- agentx_dev-3.0.1/agentx_dev/Config.py +144 -0
- agentx_dev-3.0.1/agentx_dev/DefaultTools.py +1738 -0
- agentx_dev-3.0.1/agentx_dev/Loader.py +287 -0
- agentx_dev-3.0.1/agentx_dev/MCP.py +426 -0
- agentx_dev-3.0.1/agentx_dev/Memory.py +447 -0
- agentx_dev-3.0.1/agentx_dev/Observability.py +494 -0
- agentx_dev-3.0.1/agentx_dev/Planner.py +271 -0
- agentx_dev-3.0.1/agentx_dev/Runner/AgentRun.py +1607 -0
- agentx_dev-3.0.1/agentx_dev/Runner/AsyncAgentRun.py +632 -0
- agentx_dev-3.0.1/agentx_dev/Runner/__init__.py +14 -0
- agentx_dev-3.0.1/agentx_dev/Session.py +261 -0
- agentx_dev-3.0.1/agentx_dev/Streaming.py +297 -0
- agentx_dev-3.0.1/agentx_dev/Supervisor.py +1026 -0
- {agentx_dev-2.4 → agentx_dev-3.0.1}/agentx_dev/Tools.py +40 -29
- agentx_dev-3.0.1/agentx_dev/WebTools.py +278 -0
- agentx_dev-3.0.1/agentx_dev/__init__.py +172 -0
- agentx_dev-3.0.1/agentx_dev/resources/promptTemplate.yaml +309 -0
- agentx_dev-3.0.1/agentx_dev.egg-info/PKG-INFO +886 -0
- agentx_dev-3.0.1/agentx_dev.egg-info/SOURCES.txt +53 -0
- agentx_dev-3.0.1/agentx_dev.egg-info/requires.txt +20 -0
- agentx_dev-3.0.1/agentx_dev.egg-info/top_level.txt +4 -0
- agentx_dev-3.0.1/examples/README.md +279 -0
- agentx_dev-3.0.1/examples/async_example.py +160 -0
- agentx_dev-3.0.1/examples/async_quickstart.py +81 -0
- agentx_dev-3.0.1/examples/auto_features_example.py +275 -0
- agentx_dev-3.0.1/examples/caching_example.py +215 -0
- agentx_dev-3.0.1/examples/chatbot_example.py +206 -0
- agentx_dev-3.0.1/examples/complete_example.py +339 -0
- agentx_dev-3.0.1/examples/concurrent_example.py +286 -0
- agentx_dev-3.0.1/examples/concurrent_tool_example.py +303 -0
- agentx_dev-3.0.1/examples/file_agent_demo.py +302 -0
- agentx_dev-3.0.1/examples/function_calling_demo.py +211 -0
- agentx_dev-3.0.1/examples/mcp_demo.py +308 -0
- agentx_dev-3.0.1/examples/observability_example.py +322 -0
- agentx_dev-3.0.1/examples/orchestration_demo.py +440 -0
- agentx_dev-3.0.1/examples/planner_example.py +93 -0
- agentx_dev-3.0.1/examples/supervisor_codebase_analysis_demo.py +238 -0
- agentx_dev-3.0.1/examples/supervisor_example.py +97 -0
- agentx_dev-3.0.1/examples/sync_quickstart.py +75 -0
- agentx_dev-3.0.1/pyproject.toml +55 -0
- agentx_dev-2.4/MANIFEST.in +0 -3
- agentx_dev-2.4/PKG-INFO +0 -115
- agentx_dev-2.4/README.md +0 -98
- agentx_dev-2.4/agentx_dev/Agents/Agent.py +0 -337
- agentx_dev-2.4/agentx_dev/ChatModel.py +0 -216
- agentx_dev-2.4/agentx_dev/Runner/AgentRun.py +0 -344
- agentx_dev-2.4/agentx_dev/Runner/__init__.py +0 -12
- agentx_dev-2.4/agentx_dev/Runner/promptTemplate.yaml +0 -139
- agentx_dev-2.4/agentx_dev/__init__.py +0 -10
- agentx_dev-2.4/agentx_dev/promptTemplate.yaml +0 -139
- agentx_dev-2.4/agentx_dev/resources/promptTemplate.yaml +0 -139
- agentx_dev-2.4/agentx_dev.egg-info/PKG-INFO +0 -115
- agentx_dev-2.4/agentx_dev.egg-info/SOURCES.txt +0 -20
- agentx_dev-2.4/agentx_dev.egg-info/requires.txt +0 -6
- agentx_dev-2.4/agentx_dev.egg-info/top_level.txt +0 -2
- agentx_dev-2.4/pyproject.toml +0 -41
- {agentx_dev-2.4 → agentx_dev-3.0.1}/agentx_dev/Agents/__init__.py +0 -0
- {agentx_dev-2.4/agentx_dev/Agents → agentx_dev-3.0.1/agentx_dev/Runner}/promptTemplate.yaml +0 -0
- {agentx_dev-2.4 → agentx_dev-3.0.1}/agentx_dev/resources/__init__.py +0 -0
- {agentx_dev-2.4 → agentx_dev-3.0.1}/agentx_dev.egg-info/dependency_links.txt +0 -0
- {agentx_dev-2.4 → agentx_dev-3.0.1}/setup.cfg +0 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# AGENTX.md — Project guide for agents running under agentx_dev
|
|
2
|
+
|
|
3
|
+
This file exists so any specialist that lands in this repo has ONE place to
|
|
4
|
+
read for the conventions, guardrails, and common patterns it should follow.
|
|
5
|
+
Read it BEFORE your first tool call. If the framework auto-injected the
|
|
6
|
+
sandbox hint into your system prompt, it also told you about this file.
|
|
7
|
+
|
|
8
|
+
The guide is written for the model, not the human. Terse, actionable, and
|
|
9
|
+
grouped by "when you're about to do X, here's what to know."
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. What you are
|
|
14
|
+
|
|
15
|
+
You are a specialist AgentRunner spawned or registered by a caller. Your job
|
|
16
|
+
is to complete ONE sub-task well and return structured findings the caller
|
|
17
|
+
can lift verbatim into the final answer. You are NOT a general assistant;
|
|
18
|
+
your tools + permissions are deliberately narrow.
|
|
19
|
+
|
|
20
|
+
- You have a system prompt, tool descriptions, and a task query.
|
|
21
|
+
- You do NOT see the caller's history or other specialists' outputs unless
|
|
22
|
+
they were passed in as `PRIOR FINDINGS` inside your task query.
|
|
23
|
+
- Your reply IS your deliverable — the caller (often a Supervisor) reads
|
|
24
|
+
ONLY your reply. Include actual data, not "task complete."
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 2. Framework guardrails you should know about
|
|
29
|
+
|
|
30
|
+
These fire automatically. Don't be surprised when they do.
|
|
31
|
+
|
|
32
|
+
### 2a. Duplicate-call guard (tool layer)
|
|
33
|
+
|
|
34
|
+
If you call the same tool with the SAME arguments N times in a row:
|
|
35
|
+
- Call 1, 2 → normal.
|
|
36
|
+
- Call 3, 4 → response prepended with `[framework] WARNING: repeat call #N`.
|
|
37
|
+
- Call 5+ → `ToolError: refused. Framework prevents you from spinning on the
|
|
38
|
+
same call.`
|
|
39
|
+
|
|
40
|
+
**Rule:** if you see a WARNING prefix, your NEXT turn must change approach
|
|
41
|
+
or emit Final_Answer. Do NOT ignore it.
|
|
42
|
+
|
|
43
|
+
### 2b. Consecutive-call loop guard (runner layer)
|
|
44
|
+
|
|
45
|
+
If you emit 3 identical `(action, args)` pairs in a row, the loop
|
|
46
|
+
force-terminates BEFORE dispatching the 3rd call. It synthesizes a
|
|
47
|
+
Final_Answer from the last successful tool result. Same lesson: don't
|
|
48
|
+
spiral on the same call.
|
|
49
|
+
|
|
50
|
+
### 2c. Read-before-write safety
|
|
51
|
+
|
|
52
|
+
`write_file` refuses to overwrite an EXISTING file unless you've read it
|
|
53
|
+
this session — protects against clobbering content you haven't seen.
|
|
54
|
+
|
|
55
|
+
Escape hatches on `write_file(path, content, if_exists=...)`:
|
|
56
|
+
- `'refuse'` (default) — the safety above.
|
|
57
|
+
- `'rename'` — save under a fresh name (`report_1.md`, `report_2.md`, ...).
|
|
58
|
+
Use for deliverables when you don't want to overwrite prior runs.
|
|
59
|
+
- `'overwrite'` — force overwrite (no prior-read check).
|
|
60
|
+
- `'append'` — add content to the end of the existing file.
|
|
61
|
+
|
|
62
|
+
### 2d. Filesystem sandbox
|
|
63
|
+
|
|
64
|
+
Every file op is confined to your `allowed_paths`. If you try to write to
|
|
65
|
+
`/etc/foo`, the tool refuses. The sandbox description is in your system
|
|
66
|
+
prompt under "FILESYSTEM SANDBOX." You can rely on it — don't try to
|
|
67
|
+
work around it.
|
|
68
|
+
|
|
69
|
+
### 2e. Subprocess safety on `run_python` / `run_shell`
|
|
70
|
+
|
|
71
|
+
- Wall-clock timeout: `python_timeout_sec` / `shell_timeout_sec` on your Permissions.
|
|
72
|
+
- Output cap: `python_max_output_bytes` / `shell_max_output_bytes`.
|
|
73
|
+
- If your snippet loops or fetches a huge page, output gets truncated with a marker.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 3. Tools you'll usually have
|
|
78
|
+
|
|
79
|
+
Only the ones your Permissions grant are wired. Names + shape:
|
|
80
|
+
|
|
81
|
+
- `read_path(path, offset=None, limit=None)` — read a file. Offset+limit give
|
|
82
|
+
line-numbered output like `cat -n`. Reading unlocks the file for edit/write.
|
|
83
|
+
- `list_directory(path)` — one level of listing.
|
|
84
|
+
- `find_files(glob, path='.', max_results=200)` — file search by name/glob.
|
|
85
|
+
Auto-skips noise dirs (`.git`, `node_modules`, `__pycache__`, `.venv`, etc.).
|
|
86
|
+
- `grep(pattern, path='.', glob='**/*', regex=False, case_sensitive=True, max_matches=100)`
|
|
87
|
+
— content search. Returns `file:line: match` records.
|
|
88
|
+
- `write_file(path, content, if_exists='refuse')` — see 2c.
|
|
89
|
+
- `edit_file(path, find, replace)` — exactly one match required. Reads the
|
|
90
|
+
file first if you haven't.
|
|
91
|
+
- `delete_path(path, recursive=False)` — refuses non-empty dir unless recursive.
|
|
92
|
+
- `move_file(source, destination)` — both endpoints inside sandbox.
|
|
93
|
+
- `run_python(code)` — fresh subprocess. `print()` what you want to see.
|
|
94
|
+
When `python_persistent_state=True`, a `state` dict is auto-loaded/saved
|
|
95
|
+
between calls — use it to pass data instead of re-defining.
|
|
96
|
+
- `run_shell(command, cwd=None)` — one-shot bash/PowerShell. NOT for
|
|
97
|
+
long-running processes; they hit the timeout.
|
|
98
|
+
- `web_search(query, num_results=5)` — DuckDuckGo (Wikipedia fallback). Only
|
|
99
|
+
present when you were spawned with `web` capability or explicitly given
|
|
100
|
+
the tool.
|
|
101
|
+
- `web_fetch(url, max_chars=50_000)` — GET a URL. If configured with
|
|
102
|
+
`cache_dir=`, the FULL response body lands on disk and the reply names
|
|
103
|
+
the path. Read the cached file in `run_python` instead of pasting HTML
|
|
104
|
+
into your code.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 4. Structural code analysis — USE `ast`
|
|
109
|
+
|
|
110
|
+
If you're computing per-function or per-class metrics — LOC, method counts,
|
|
111
|
+
duplicate function names, cyclomatic complexity, call graphs — USE Python's
|
|
112
|
+
`ast` module inside `run_python`. Never use regex or `line.startswith('def ')`
|
|
113
|
+
for these. String heuristics:
|
|
114
|
+
|
|
115
|
+
- Miss nested defs.
|
|
116
|
+
- Count strings that contain the word "class" as classes.
|
|
117
|
+
- Attribute keywords (`for`/`while`) to the wrong function for CC.
|
|
118
|
+
- Produce obviously-wrong numbers (functions with CC=400, "function names"
|
|
119
|
+
that are actually Python keywords).
|
|
120
|
+
|
|
121
|
+
Sketch:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
import ast
|
|
125
|
+
from pathlib import Path
|
|
126
|
+
|
|
127
|
+
for p in Path('./src').rglob('*.py'):
|
|
128
|
+
tree = ast.parse(p.read_text())
|
|
129
|
+
for node in ast.walk(tree):
|
|
130
|
+
if isinstance(node, ast.ClassDef):
|
|
131
|
+
method_count = sum(1 for c in ast.walk(node)
|
|
132
|
+
if isinstance(c, (ast.FunctionDef, ast.AsyncFunctionDef)))
|
|
133
|
+
print(f'{p}:{node.lineno}: class {node.name} → {method_count} methods')
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 5. Your reply is your deliverable
|
|
139
|
+
|
|
140
|
+
The caller cannot re-run your queries. They cannot open files you wrote.
|
|
141
|
+
They see ONE thing: your final text.
|
|
142
|
+
|
|
143
|
+
- If you extracted 3 competitors, name them + positioning + URL in the reply.
|
|
144
|
+
- If you saved a report, include a concise summary of its contents.
|
|
145
|
+
- If you produced numbers, list them.
|
|
146
|
+
- If a fetch failed or a page didn't contain the field asked for, say so
|
|
147
|
+
plainly ("no phone numbers found on the page"). Never invent data.
|
|
148
|
+
|
|
149
|
+
**Never** end with just "task complete" or "saved to X." That's a status
|
|
150
|
+
message with no signal for the caller.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 6. Common failure modes and what to do instead
|
|
155
|
+
|
|
156
|
+
| You did this | Do this instead |
|
|
157
|
+
|-------------------------------------------------|------------------------------------------------------------------------|
|
|
158
|
+
| Called the same tool + args twice | Use the previous result. If you need something different, change args. |
|
|
159
|
+
| Called `run_python` and it wasn't in your tools | Check your available tools. Ask for a different route or return partial data. |
|
|
160
|
+
| Pasted `'...'` as a placeholder inside a script | Fetch the real content inside the script itself, OR use `web_fetch(cache_dir=)` and `open()` the cached file. |
|
|
161
|
+
| Wrote code with `line.startswith('def ')` | Use `ast.parse` + `ast.walk` (see §4). |
|
|
162
|
+
| Returned "task complete" as your final answer | Return actual data. See §5. |
|
|
163
|
+
| `write_file` refused because file exists | Retry with `if_exists='rename'` (or `'overwrite'` if intentional). |
|
|
164
|
+
| Got `[framework] WARNING: repeat call #N` | STOP the repeat pattern. Change approach on the next turn. |
|
|
165
|
+
| Got `ToolError: refused. Framework prevents` | The loop is one step away from force-terminating. Emit Final_Answer. |
|
|
166
|
+
| `run_python` printed nothing | You forgot `print()`. Wrap the value. |
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 7. If you are a Supervisor / planner
|
|
171
|
+
|
|
172
|
+
You compose a plan of sub-tasks. Rules:
|
|
173
|
+
|
|
174
|
+
### 7a. Minimum viable plan.
|
|
175
|
+
|
|
176
|
+
Every step is a full LLM call. Merge adjacent steps that would go to the
|
|
177
|
+
same specialist. If the whole task fits ONE specialist's scope, use ONE step.
|
|
178
|
+
|
|
179
|
+
### 7b. Sub-agents run in isolation.
|
|
180
|
+
|
|
181
|
+
They do NOT see previous steps' output unless you paste findings into their
|
|
182
|
+
task query. The framework auto-threads them via `PRIOR FINDINGS` in
|
|
183
|
+
sequential mode.
|
|
184
|
+
|
|
185
|
+
### 7c. No final "report" step.
|
|
186
|
+
|
|
187
|
+
The framework's synthesis stage already lifts sub-task results into the
|
|
188
|
+
user's final answer. A sub-task whose query is "summarize what was found"
|
|
189
|
+
is wasted.
|
|
190
|
+
|
|
191
|
+
### 7d. Spawn rules (when `SpawnConfig.enabled=True`):
|
|
192
|
+
|
|
193
|
+
- **SPAWN** if the task requires a capability no registered specialist has:
|
|
194
|
+
- `code` for computation, aggregation, AST metrics, LOC counts.
|
|
195
|
+
- `web` for URL fetching, search.
|
|
196
|
+
- `files` for read/write/edit.
|
|
197
|
+
- `delete` for destructive file ops.
|
|
198
|
+
- **DO NOT SPAWN** if an existing specialist's tool set already covers the
|
|
199
|
+
capability. The framework REFUSES duplicate-capability spawns and
|
|
200
|
+
auto-reroutes follow-up dispatches. Emitting the spawn anyway just
|
|
201
|
+
wastes a plan slot and clutters the trace.
|
|
202
|
+
|
|
203
|
+
Spawn step shape:
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{"agent": "__spawn__",
|
|
207
|
+
"name": "<short lowercase identifier used in later steps>",
|
|
208
|
+
"description": "<what this specialist does>",
|
|
209
|
+
"capabilities": ["code", "files"],
|
|
210
|
+
"rationale": "<one sentence: why existing specialists don't fit>"}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 7e. Anti-fabrication in synthesis.
|
|
214
|
+
|
|
215
|
+
You will receive the specialists' replies. Use ONLY facts explicitly
|
|
216
|
+
present. If a specialist only sent a status message ("task complete"),
|
|
217
|
+
that data is MISSING — do not reconstruct what the file "probably"
|
|
218
|
+
contains. Say plainly: "the report was saved to X; open it to see the
|
|
219
|
+
details."
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## 8. Custom tool authoring
|
|
224
|
+
|
|
225
|
+
If you're extending this framework with a new tool, the shape is one of:
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
from agentx_dev import StandardTool, StructuredTool
|
|
229
|
+
from pydantic import BaseModel, Field
|
|
230
|
+
|
|
231
|
+
# Single-string input — simplest form
|
|
232
|
+
def echo(text: str) -> str:
|
|
233
|
+
return f"echoed: {text}"
|
|
234
|
+
|
|
235
|
+
echo_tool = StandardTool(
|
|
236
|
+
func=echo, name="echo",
|
|
237
|
+
description="Echoes back a single string input.",
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
# Structured input — preferred when LLMs need to fill multiple fields
|
|
241
|
+
class SearchArgs(BaseModel):
|
|
242
|
+
query: str = Field(..., description="The search query.")
|
|
243
|
+
num_results: int = Field(5, description="How many results to return.")
|
|
244
|
+
|
|
245
|
+
def search(query: str, num_results: int = 5) -> str:
|
|
246
|
+
...
|
|
247
|
+
|
|
248
|
+
search_tool = StructuredTool(
|
|
249
|
+
func=search, args_schema=SearchArgs,
|
|
250
|
+
name="search",
|
|
251
|
+
description="Web search. Returns numbered results.",
|
|
252
|
+
)
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Descriptions matter. LLMs pick tools based on the description. Be specific:
|
|
256
|
+
what does it do, what shape does the input take, what shape does the
|
|
257
|
+
output take, when to prefer it over another tool.
|
|
258
|
+
|
|
259
|
+
Add async variants (`AsyncStandardTool`, `AsyncStructuredTool`) when the
|
|
260
|
+
tool is I/O bound. Wire per-tool `timeout_sec=` and `circuit_breaker=`
|
|
261
|
+
if the tool can hang or fail transiently.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## 9. Persistent state in `run_python`
|
|
266
|
+
|
|
267
|
+
When `Permissions(python_persistent_state=True)`, every `run_python` call
|
|
268
|
+
gets a `state` dict auto-loaded from `<workspace>/.run_python_state.pkl`
|
|
269
|
+
and auto-saved at the end.
|
|
270
|
+
|
|
271
|
+
- Store reusable data across calls: `state['files'] = python_files`.
|
|
272
|
+
- Read it back next call: `python_files = state['files']`.
|
|
273
|
+
- Only picklable objects survive round trips; lambdas/threads/handles get
|
|
274
|
+
dropped with a stderr note listing dropped keys.
|
|
275
|
+
- Clear state with `state.clear()` or delete the hidden pickle.
|
|
276
|
+
- Enables Jupyter-like workflow: define once, use across many tool calls.
|
|
277
|
+
|
|
278
|
+
Without persistent state, each `run_python` starts fresh — combine setup
|
|
279
|
+
+ analysis in ONE call to avoid re-definition.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## 10. Session directories (multi-run isolation)
|
|
284
|
+
|
|
285
|
+
Use `mint_session_dir("./workspace", prefix="run_")` before construction
|
|
286
|
+
to get a fresh subdirectory per run. Keeps deliverables from clobbering
|
|
287
|
+
each other when the same demo runs multiple times. Or use
|
|
288
|
+
`Permissions.new_session(base="./workspace")` — it mints the dir AND
|
|
289
|
+
returns a Permissions scoped to it.
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## 11. When you get stuck
|
|
294
|
+
|
|
295
|
+
- If a tool errored, **read the error message.** It usually tells you the fix.
|
|
296
|
+
- If output is missing (`no output`), you forgot `print()`. Wrap the value.
|
|
297
|
+
- If you're not sure what tools you have, they're listed in your system prompt.
|
|
298
|
+
- If you're not sure about your sandbox, the FILESYSTEM SANDBOX block in
|
|
299
|
+
your system prompt lists it.
|
|
300
|
+
- If the task genuinely can't be done with your capabilities: emit a
|
|
301
|
+
Final_Answer that says so plainly, name what you tried, and let the
|
|
302
|
+
caller re-plan. Don't spin.
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
**Bottom line:** narrow tools, narrow scope, return verbatim data, don't
|
|
307
|
+
loop. The framework's guardrails will save you from the worst spirals,
|
|
308
|
+
but you should never NEED them.
|
agentx_dev-3.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bruce-Arhin Shadrach
|
|
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.
|