agentify-toolkit 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.
- agentify/__init__.py +21 -0
- agentify/agentify.py +61 -0
- agentify/agents.py +37 -0
- agentify/cli.py +291 -0
- agentify/cli_config.py +100 -0
- agentify/cli_ui.py +44 -0
- agentify/providers/__init__.py +5 -0
- agentify/providers/anthropic.py +15 -0
- agentify/providers/bedrock.py +30 -0
- agentify/providers/google.py +10 -0
- agentify/providers/openai.py +11 -0
- agentify/providers/x.py +12 -0
- agentify/runtime_client.py +23 -0
- agentify/specs.py +19 -0
- agentify/ui/basic-chat.css +230 -0
- agentify/ui/chat.css +230 -0
- agentify/ui/chat.html +107 -0
- agentify/ui/htmx.min.js +1 -0
- agentify/ui/retro-chat.css +353 -0
- agentify/web.py +60 -0
- agentify_toolkit-0.1.0.dist-info/METADATA +266 -0
- agentify_toolkit-0.1.0.dist-info/RECORD +27 -0
- agentify_toolkit-0.1.0.dist-info/WHEEL +5 -0
- agentify_toolkit-0.1.0.dist-info/entry_points.txt +2 -0
- agentify_toolkit-0.1.0.dist-info/licenses/LICENSE +100 -0
- agentify_toolkit-0.1.0.dist-info/licenses/NOTICE +6 -0
- agentify_toolkit-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&display=swap");
|
|
2
|
+
|
|
3
|
+
body {
|
|
4
|
+
font-family: "IBM Plex Mono", "Courier New", monospace;
|
|
5
|
+
background: #0a0e14;
|
|
6
|
+
margin: 0;
|
|
7
|
+
display: flex;
|
|
8
|
+
justify-content: center;
|
|
9
|
+
align-items: center;
|
|
10
|
+
height: 100vh;
|
|
11
|
+
padding: 2rem;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
position: relative;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Scanline effect */
|
|
18
|
+
body::before {
|
|
19
|
+
content: "";
|
|
20
|
+
position: fixed;
|
|
21
|
+
top: 0;
|
|
22
|
+
left: 0;
|
|
23
|
+
width: 100%;
|
|
24
|
+
height: 100%;
|
|
25
|
+
background: repeating-linear-gradient(
|
|
26
|
+
0deg,
|
|
27
|
+
rgba(0, 255, 0, 0.03) 0px,
|
|
28
|
+
transparent 1px,
|
|
29
|
+
transparent 2px,
|
|
30
|
+
rgba(0, 255, 0, 0.03) 3px
|
|
31
|
+
);
|
|
32
|
+
pointer-events: none;
|
|
33
|
+
z-index: 1000;
|
|
34
|
+
animation: scanline 8s linear infinite;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@keyframes scanline {
|
|
38
|
+
0% {
|
|
39
|
+
transform: translateY(0);
|
|
40
|
+
}
|
|
41
|
+
100% {
|
|
42
|
+
transform: translateY(10px);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* CRT flicker */
|
|
47
|
+
body::after {
|
|
48
|
+
content: "";
|
|
49
|
+
position: fixed;
|
|
50
|
+
top: 0;
|
|
51
|
+
left: 0;
|
|
52
|
+
width: 100%;
|
|
53
|
+
height: 100%;
|
|
54
|
+
background: rgba(18, 16, 16, 0.1);
|
|
55
|
+
opacity: 0;
|
|
56
|
+
pointer-events: none;
|
|
57
|
+
animation: flicker 0.15s infinite;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@keyframes flicker {
|
|
61
|
+
0% {
|
|
62
|
+
opacity: 0.05;
|
|
63
|
+
}
|
|
64
|
+
50% {
|
|
65
|
+
opacity: 0.1;
|
|
66
|
+
}
|
|
67
|
+
100% {
|
|
68
|
+
opacity: 0.05;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
#chat-container {
|
|
73
|
+
width: 100%;
|
|
74
|
+
max-width: 700px;
|
|
75
|
+
background: #0d1117;
|
|
76
|
+
border-radius: 12px;
|
|
77
|
+
box-shadow: 0 0 80px rgba(0, 255, 65, 0.15), 0 0 40px rgba(0, 255, 65, 0.1),
|
|
78
|
+
inset 0 0 60px rgba(0, 0, 0, 0.5);
|
|
79
|
+
display: flex;
|
|
80
|
+
flex-direction: column;
|
|
81
|
+
padding: 0;
|
|
82
|
+
height: 650px;
|
|
83
|
+
border: 2px solid #1a3a1f;
|
|
84
|
+
position: relative;
|
|
85
|
+
overflow: hidden;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Terminal header bar */
|
|
89
|
+
#chat-container::before {
|
|
90
|
+
content: "";
|
|
91
|
+
position: absolute;
|
|
92
|
+
top: 0;
|
|
93
|
+
left: 0;
|
|
94
|
+
right: 0;
|
|
95
|
+
height: 32px;
|
|
96
|
+
background: linear-gradient(180deg, #1a3a1f 0%, #0f1f13 100%);
|
|
97
|
+
border-bottom: 1px solid #00ff41;
|
|
98
|
+
z-index: 10;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Terminal buttons */
|
|
102
|
+
#chat-container::after {
|
|
103
|
+
content: "● ● ●";
|
|
104
|
+
position: absolute;
|
|
105
|
+
top: 9px;
|
|
106
|
+
left: 12px;
|
|
107
|
+
font-size: 8px;
|
|
108
|
+
color: #00ff41;
|
|
109
|
+
letter-spacing: 4px;
|
|
110
|
+
z-index: 11;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
#chat-header {
|
|
114
|
+
font-family: "IBM Plex Mono", monospace;
|
|
115
|
+
font-size: 0.75rem;
|
|
116
|
+
font-weight: 500;
|
|
117
|
+
color: #00ff41;
|
|
118
|
+
text-align: center;
|
|
119
|
+
padding: 8px;
|
|
120
|
+
margin: 0;
|
|
121
|
+
position: absolute;
|
|
122
|
+
top: 0;
|
|
123
|
+
left: 0;
|
|
124
|
+
right: 0;
|
|
125
|
+
z-index: 11;
|
|
126
|
+
text-shadow: 0 0 10px rgba(0, 255, 65, 0.8);
|
|
127
|
+
letter-spacing: 2px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.tagline {
|
|
131
|
+
font-family: "IBM Plex Mono", monospace;
|
|
132
|
+
font-size: 0.7rem;
|
|
133
|
+
color: #00ff41;
|
|
134
|
+
opacity: 0.5;
|
|
135
|
+
text-align: center;
|
|
136
|
+
margin-top: 40px;
|
|
137
|
+
margin-bottom: 1rem;
|
|
138
|
+
padding: 0 2rem;
|
|
139
|
+
letter-spacing: 1px;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
#chat {
|
|
143
|
+
flex-grow: 1;
|
|
144
|
+
overflow-y: auto;
|
|
145
|
+
margin: 50px 2rem 1.5rem 2rem;
|
|
146
|
+
padding-right: 0.5rem;
|
|
147
|
+
display: flex;
|
|
148
|
+
flex-direction: column;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* Custom scrollbar */
|
|
152
|
+
#chat::-webkit-scrollbar {
|
|
153
|
+
width: 8px;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
#chat::-webkit-scrollbar-track {
|
|
157
|
+
background: #0a0e14;
|
|
158
|
+
border-left: 1px solid #1a3a1f;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
#chat::-webkit-scrollbar-thumb {
|
|
162
|
+
background: #00ff41;
|
|
163
|
+
box-shadow: 0 0 10px rgba(0, 255, 65, 0.5);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
#chat::-webkit-scrollbar-thumb:hover {
|
|
167
|
+
background: #00ff65;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.message {
|
|
171
|
+
padding: 0.5rem 0;
|
|
172
|
+
margin-bottom: 0.75rem;
|
|
173
|
+
position: relative;
|
|
174
|
+
max-width: 100%;
|
|
175
|
+
word-wrap: break-word;
|
|
176
|
+
line-height: 1.6;
|
|
177
|
+
animation: terminalType 0.5s ease-in;
|
|
178
|
+
font-size: 0.9rem;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@keyframes terminalType {
|
|
182
|
+
from {
|
|
183
|
+
opacity: 0;
|
|
184
|
+
transform: translateX(-10px);
|
|
185
|
+
}
|
|
186
|
+
to {
|
|
187
|
+
opacity: 1;
|
|
188
|
+
transform: translateX(0);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.message.user {
|
|
193
|
+
color: #00ff41;
|
|
194
|
+
text-shadow: 0 0 8px rgba(0, 255, 65, 0.6);
|
|
195
|
+
align-self: flex-start;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.message.user::before {
|
|
199
|
+
content: "> ";
|
|
200
|
+
color: #00ff65;
|
|
201
|
+
font-weight: 600;
|
|
202
|
+
text-shadow: 0 0 10px rgba(0, 255, 65, 0.8);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.message.agent {
|
|
206
|
+
color: #33ff77;
|
|
207
|
+
text-shadow: 0 0 5px rgba(51, 255, 119, 0.4);
|
|
208
|
+
align-self: flex-start;
|
|
209
|
+
opacity: 0.9;
|
|
210
|
+
padding-left: 1.2rem;
|
|
211
|
+
border-left: 2px solid #1a3a1f;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.message.agent.typing {
|
|
215
|
+
font-style: normal;
|
|
216
|
+
color: #00ff41;
|
|
217
|
+
opacity: 0.6;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.message.agent.typing::after {
|
|
221
|
+
content: "▊";
|
|
222
|
+
animation: blink 1s infinite;
|
|
223
|
+
margin-left: 4px;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
@keyframes blink {
|
|
227
|
+
0%,
|
|
228
|
+
49% {
|
|
229
|
+
opacity: 1;
|
|
230
|
+
}
|
|
231
|
+
50%,
|
|
232
|
+
100% {
|
|
233
|
+
opacity: 0;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.timestamp {
|
|
238
|
+
font-size: 0.65rem;
|
|
239
|
+
color: #00ff41;
|
|
240
|
+
margin-top: 4px;
|
|
241
|
+
display: block;
|
|
242
|
+
opacity: 0.3;
|
|
243
|
+
font-family: "IBM Plex Mono", monospace;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
form {
|
|
247
|
+
display: flex;
|
|
248
|
+
gap: 0.75rem;
|
|
249
|
+
align-items: center;
|
|
250
|
+
padding: 0 2rem 2rem 2rem;
|
|
251
|
+
position: relative;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
form::before {
|
|
255
|
+
content: "$";
|
|
256
|
+
position: absolute;
|
|
257
|
+
left: 2.75rem;
|
|
258
|
+
color: #00ff41;
|
|
259
|
+
font-weight: 600;
|
|
260
|
+
text-shadow: 0 0 10px rgba(0, 255, 65, 0.8);
|
|
261
|
+
pointer-events: none;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
#question-input {
|
|
265
|
+
flex-grow: 1;
|
|
266
|
+
padding: 0.75rem 1rem 0.75rem 2rem;
|
|
267
|
+
font-size: 0.9rem;
|
|
268
|
+
border-radius: 4px;
|
|
269
|
+
border: 2px solid #1a3a1f;
|
|
270
|
+
outline: none;
|
|
271
|
+
background-color: #0a0e14;
|
|
272
|
+
transition: all 0.2s ease-in-out;
|
|
273
|
+
font-family: "IBM Plex Mono", monospace;
|
|
274
|
+
color: #00ff41;
|
|
275
|
+
text-shadow: 0 0 5px rgba(0, 255, 65, 0.5);
|
|
276
|
+
caret-color: #00ff41;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
#question-input:focus {
|
|
280
|
+
border-color: #00ff41;
|
|
281
|
+
box-shadow: 0 0 20px rgba(0, 255, 65, 0.3),
|
|
282
|
+
inset 0 0 10px rgba(0, 255, 65, 0.1);
|
|
283
|
+
background-color: #0d1117;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
#question-input::placeholder {
|
|
287
|
+
color: #00ff41;
|
|
288
|
+
opacity: 0.3;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
button {
|
|
292
|
+
background: #0d1117;
|
|
293
|
+
color: #00ff41;
|
|
294
|
+
border: 2px solid #1a3a1f;
|
|
295
|
+
border-radius: 4px;
|
|
296
|
+
padding: 0.75rem 1.5rem;
|
|
297
|
+
font-size: 0.85rem;
|
|
298
|
+
font-weight: 600;
|
|
299
|
+
cursor: pointer;
|
|
300
|
+
transition: all 0.2s ease-in-out;
|
|
301
|
+
white-space: nowrap;
|
|
302
|
+
font-family: "IBM Plex Mono", monospace;
|
|
303
|
+
text-shadow: 0 0 8px rgba(0, 255, 65, 0.6);
|
|
304
|
+
letter-spacing: 1px;
|
|
305
|
+
text-transform: uppercase;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
button:hover {
|
|
309
|
+
background: #1a3a1f;
|
|
310
|
+
border-color: #00ff41;
|
|
311
|
+
box-shadow: 0 0 20px rgba(0, 255, 65, 0.4),
|
|
312
|
+
inset 0 0 10px rgba(0, 255, 65, 0.1);
|
|
313
|
+
transform: translateY(-1px);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
button:active {
|
|
317
|
+
transform: translateY(0);
|
|
318
|
+
box-shadow: 0 0 10px rgba(0, 255, 65, 0.3),
|
|
319
|
+
inset 0 0 15px rgba(0, 255, 65, 0.2);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
button:disabled {
|
|
323
|
+
opacity: 0.3;
|
|
324
|
+
cursor: not-allowed;
|
|
325
|
+
transform: none;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
button:focus {
|
|
329
|
+
outline: 2px solid #00ff41;
|
|
330
|
+
outline-offset: 2px;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* Vignette effect */
|
|
334
|
+
#chat-container {
|
|
335
|
+
box-shadow: 0 0 80px rgba(0, 255, 65, 0.15), 0 0 40px rgba(0, 255, 65, 0.1),
|
|
336
|
+
inset 0 0 100px rgba(0, 0, 0, 0.8);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* Responsive adjustments */
|
|
340
|
+
@media (max-width: 640px) {
|
|
341
|
+
body {
|
|
342
|
+
padding: 1rem;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
#chat-container {
|
|
346
|
+
height: calc(100vh - 2rem);
|
|
347
|
+
max-width: 100%;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.message {
|
|
351
|
+
font-size: 0.85rem;
|
|
352
|
+
}
|
|
353
|
+
}
|
agentify/web.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# web.py
|
|
2
|
+
from fastapi import FastAPI, Form
|
|
3
|
+
from fastapi.staticfiles import StaticFiles
|
|
4
|
+
from fastapi.responses import HTMLResponse
|
|
5
|
+
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
import uvicorn
|
|
8
|
+
|
|
9
|
+
app = FastAPI()
|
|
10
|
+
|
|
11
|
+
# app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
12
|
+
ui_path = Path(__file__).parent / "ui"
|
|
13
|
+
|
|
14
|
+
app.mount("/ui", StaticFiles(directory=ui_path), name="ui")
|
|
15
|
+
|
|
16
|
+
@app.get("/", response_class=HTMLResponse)
|
|
17
|
+
async def home():
|
|
18
|
+
HTML_PATH = Path(__file__).parent / "ui" / "chat.html"
|
|
19
|
+
with open(HTML_PATH, "r", encoding="utf-8") as f:
|
|
20
|
+
html_content = f.read()
|
|
21
|
+
|
|
22
|
+
agent_name = getattr(app.state, "agent_name", "Agent").upper()
|
|
23
|
+
agent_model_id = getattr(app.state, "model_id", "Agent")
|
|
24
|
+
agent_provider = getattr(app.state, "provider", "Agent")
|
|
25
|
+
html_content = html_content.replace("{{AGENT_NAME}}", agent_name)
|
|
26
|
+
html_content = html_content.replace("{{AGENT_MODEL_ID}}", agent_model_id)
|
|
27
|
+
html_content = html_content.replace("{{AGENT_PROVIDER}}", agent_provider)
|
|
28
|
+
|
|
29
|
+
return HTMLResponse(content=html_content)
|
|
30
|
+
|
|
31
|
+
@app.post("/ask", response_class=HTMLResponse)
|
|
32
|
+
async def ask_agent(question: str = Form(...)):
|
|
33
|
+
agent = app.state.agent
|
|
34
|
+
|
|
35
|
+
question = f"Answer with this role:{agent.role} the question: {question}"
|
|
36
|
+
try:
|
|
37
|
+
answer = agent.run(question)
|
|
38
|
+
except Exception:
|
|
39
|
+
answer = "Agent is currently busy. Please try again in a few seconds."
|
|
40
|
+
|
|
41
|
+
# answer = agent.run(question)
|
|
42
|
+
|
|
43
|
+
# Append chat messages in HTML
|
|
44
|
+
html = f"""
|
|
45
|
+
<div class="message">
|
|
46
|
+
<span class="agent"><strong>{agent.name}</strong>:</span> {answer}
|
|
47
|
+
</div>
|
|
48
|
+
"""
|
|
49
|
+
return HTMLResponse(content=html)
|
|
50
|
+
|
|
51
|
+
def run_web_ui(agent, host="127.0.0.1", port=8001):
|
|
52
|
+
"""
|
|
53
|
+
Run the web UI with the given agent.
|
|
54
|
+
Stores the agent in app.state and starts uvicorn.
|
|
55
|
+
"""
|
|
56
|
+
app.state.agent = agent
|
|
57
|
+
app.state.agent_name = agent.name
|
|
58
|
+
app.state.provider = agent.provider
|
|
59
|
+
app.state.model_id = agent.model_id
|
|
60
|
+
uvicorn.run(app, host=host, port=port)
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentify_toolkit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Declarative AI toolkit
|
|
5
|
+
Author-email: Lewis Sheridan <lewis@backplane.dev>
|
|
6
|
+
License: Apache License
|
|
7
|
+
Version 2.0, January 2004
|
|
8
|
+
http://www.apache.org/licenses/
|
|
9
|
+
|
|
10
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
11
|
+
|
|
12
|
+
1. Definitions.
|
|
13
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
14
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
15
|
+
|
|
16
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
17
|
+
the copyright owner that is granting the License.
|
|
18
|
+
|
|
19
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
20
|
+
other entities that control, are controlled by, or are under common
|
|
21
|
+
control with that entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work.
|
|
38
|
+
|
|
39
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
40
|
+
form, that is based on (or derived from) the Work and for which the
|
|
41
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
42
|
+
represent, as a whole, an original work of authorship.
|
|
43
|
+
|
|
44
|
+
"Contribution" shall mean any work of authorship, including
|
|
45
|
+
the original version of the Work and any modifications or additions
|
|
46
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
47
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
48
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
49
|
+
the copyright owner.
|
|
50
|
+
|
|
51
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
52
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
53
|
+
subsequently incorporated within the Work.
|
|
54
|
+
|
|
55
|
+
2. Grant of Copyright License.
|
|
56
|
+
Subject to the terms and conditions of this License, each Contributor
|
|
57
|
+
hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
|
|
58
|
+
royalty-free, irrevocable copyright license to reproduce, prepare
|
|
59
|
+
Derivative Works of, publicly display, publicly perform, sublicense,
|
|
60
|
+
and distribute the Work and such Derivative Works in Source or Object
|
|
61
|
+
form.
|
|
62
|
+
|
|
63
|
+
3. Grant of Patent License.
|
|
64
|
+
Subject to the terms and conditions of this License, each Contributor
|
|
65
|
+
hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
|
|
66
|
+
royalty-free, irrevocable patent license to make, have made, use,
|
|
67
|
+
offer to sell, sell, import, and otherwise transfer the Work.
|
|
68
|
+
|
|
69
|
+
4. Redistribution.
|
|
70
|
+
You may reproduce and distribute copies of the Work or Derivative
|
|
71
|
+
Works thereof in any medium, with or without modifications, provided
|
|
72
|
+
that You meet the following conditions:
|
|
73
|
+
|
|
74
|
+
(a) You must give any other recipients of the Work or
|
|
75
|
+
Derivative Works a copy of this License; and
|
|
76
|
+
|
|
77
|
+
(b) You must cause any modified files to carry prominent notices
|
|
78
|
+
stating that You changed the files; and
|
|
79
|
+
|
|
80
|
+
(c) You must retain, in the Source form of any Derivative Works,
|
|
81
|
+
all copyright, patent, trademark, and attribution notices.
|
|
82
|
+
|
|
83
|
+
5. Submission of Contributions.
|
|
84
|
+
Unless You explicitly state otherwise, any Contribution intentionally
|
|
85
|
+
submitted for inclusion in the Work shall be under the terms and
|
|
86
|
+
conditions of this License.
|
|
87
|
+
|
|
88
|
+
6. Trademarks.
|
|
89
|
+
This License does not grant permission to use the trade names,
|
|
90
|
+
trademarks, service marks, or product names of the Licensor.
|
|
91
|
+
|
|
92
|
+
7. Disclaimer of Warranty.
|
|
93
|
+
Unless required by applicable law or agreed to in writing, Licensor
|
|
94
|
+
provides the Work on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
|
|
95
|
+
OF ANY KIND.
|
|
96
|
+
|
|
97
|
+
8. Limitation of Liability.
|
|
98
|
+
In no event shall any Contributor be liable for any damages arising
|
|
99
|
+
from the use of the Work.
|
|
100
|
+
|
|
101
|
+
9. Accepting Warranty or Additional Liability.
|
|
102
|
+
While redistributing the Work, You may choose to offer support or
|
|
103
|
+
warranty obligations on Your own behalf.
|
|
104
|
+
|
|
105
|
+
END OF TERMS AND CONDITIONS
|
|
106
|
+
|
|
107
|
+
Project-URL: Homepage, https://github.com/backplane-cloud/agentify-toolkit
|
|
108
|
+
Project-URL: Issues, https://github.com/backplane-cloud/agentify-toolkit/issues
|
|
109
|
+
Keywords: ai,agents,llm,openai,anthropic,bedrock
|
|
110
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
111
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
112
|
+
Classifier: Development Status :: 3 - Alpha
|
|
113
|
+
Classifier: Intended Audience :: Developers
|
|
114
|
+
Requires-Python: >=3.10
|
|
115
|
+
Description-Content-Type: text/markdown
|
|
116
|
+
License-File: LICENSE
|
|
117
|
+
License-File: NOTICE
|
|
118
|
+
Requires-Dist: pyyaml>=6.0
|
|
119
|
+
Requires-Dist: rich>=13.0
|
|
120
|
+
Requires-Dist: click>=8.1
|
|
121
|
+
Requires-Dist: openai>=1.0
|
|
122
|
+
Requires-Dist: anthropic>=0.25
|
|
123
|
+
Requires-Dist: boto3>=1.34
|
|
124
|
+
Requires-Dist: xai_sdk>=1.5.0
|
|
125
|
+
Requires-Dist: google-genai>=0.8
|
|
126
|
+
Requires-Dist: fastapi>=0.105
|
|
127
|
+
Requires-Dist: uvicorn>=0.26
|
|
128
|
+
Requires-Dist: python-multipart>=0.0.6
|
|
129
|
+
Dynamic: license-file
|
|
130
|
+
|
|
131
|
+
# Agent Building Toolkit - Agentify 🤖
|
|
132
|
+
|
|
133
|
+
[](https://pypi.org/project/agentify-toolkit/)
|
|
134
|
+
[](https://www.python.org/)
|
|
135
|
+
[](LICENSE)
|
|
136
|
+
[](https://colab.research.google.com/github/backplane-cloud/agentify-toolkit/blob/main/examples/notebooks/Agentify_Developer_Quickstart.ipynb)
|
|
137
|
+
|
|
138
|
+
> Agentify is a lightweight, declarative-first Library for building **AI agents** in Python
|
|
139
|
+
|
|
140
|
+
## KeyFeatures
|
|
141
|
+
|
|
142
|
+
- Declarative agent definitions via YAML.
|
|
143
|
+
- Multi-LLM support: OpenAI, Anthropic, and more.
|
|
144
|
+
- Interactive CLI with TUI menu for exploring agents.
|
|
145
|
+
- Programmatic agent creation and execution for custom workflows.
|
|
146
|
+
- Lightweight, minimal dependencies: Click + Rich + PyYAML.
|
|
147
|
+
|
|
148
|
+
## 🚀 Getting Started
|
|
149
|
+
|
|
150
|
+
Prefer a hands-on walkthrough?
|
|
151
|
+
|
|
152
|
+
- 📘 [Agentify Developer Quickstart (Jupyter)](examples/notebooks/Agentify_Developer_Quickstart.ipynb)
|
|
153
|
+
- 📄 [Agentify YAML Deep Dive](examples/notebooks/Agentify_YAML_Deep_Dive.ipynb)
|
|
154
|
+
|
|
155
|
+
## How it works
|
|
156
|
+
|
|
157
|
+
Define your agents in simple YAML files or programmatically, and run them using an interactive CLI. Agentify abstracts LLM provider integrations and provides a simplified developer experience.
|
|
158
|
+
|
|
159
|
+
## Installation
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
pip install agentify-toolkit
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Or install from source:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
git clone https://github.com/backplane-software/agentify.git
|
|
169
|
+
cd agentify
|
|
170
|
+
pip install .
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Quick Start
|
|
174
|
+
|
|
175
|
+
### 1. Create an agent YAML
|
|
176
|
+
|
|
177
|
+
```yaml
|
|
178
|
+
name: claude
|
|
179
|
+
description: AI Engineer
|
|
180
|
+
version: 0.1.0
|
|
181
|
+
model:
|
|
182
|
+
provider: anthropic
|
|
183
|
+
id: claude-sonnet-4-5
|
|
184
|
+
api_key_env: ANTHROPIC_API_KEY
|
|
185
|
+
role: |
|
|
186
|
+
You are an AI Security Engineer.
|
|
187
|
+
Provide concise, practical answers with examples.
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### 2 .Run a single agent
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
agentify run examples/agent.yaml
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
> **Overriding Model** - you can pass a provider and model parameter to override the provider and model in the YAML file
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
agentify run examples/agent.yaml --provider=openai --model=gpt-5-nano
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### 3. Run agents interactively from a folder
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
agentify run examples/agents
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 4. List agents interactively
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
agentify list agents
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Programmatic Usage
|
|
215
|
+
|
|
216
|
+
Install agentify with `pip install agentify` and then import.
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
from agentify import Agent
|
|
220
|
+
|
|
221
|
+
def main():
|
|
222
|
+
|
|
223
|
+
agent = Agent(
|
|
224
|
+
name="Grok",
|
|
225
|
+
description="X's Grok Agent",
|
|
226
|
+
provider="x",
|
|
227
|
+
model_id="grok-4",
|
|
228
|
+
role="You are an AI Security Architect specialising in X AI Grok models"
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
response = agent.run("Which AI LLM is the best in 1 sentence ?")
|
|
232
|
+
print(response)
|
|
233
|
+
|
|
234
|
+
if __name__ == "__main__":
|
|
235
|
+
main()
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## CLI Reference
|
|
239
|
+
|
|
240
|
+
| Command | Example |
|
|
241
|
+
| ------------------------------ | --------------------------- |
|
|
242
|
+
| Run agent from YAML | `agentify run <agent.yaml>` |
|
|
243
|
+
| Run all YAML Agents in folder | `agentify run <folder>` |
|
|
244
|
+
| List all YAML Agents in folder | `agentify list <folder>` |
|
|
245
|
+
|
|
246
|
+
## Adding LLM API Keys
|
|
247
|
+
|
|
248
|
+
To use the LLM Model providers, you will need an API key and they will need to be made available in your environment.
|
|
249
|
+
|
|
250
|
+
Implemented providers:
|
|
251
|
+
|
|
252
|
+
| Provider | Instruction | Link |
|
|
253
|
+
| --------- | ---------------------------------------------- | ------------------------------------ |
|
|
254
|
+
| OpenAI | `export OPENAI_API_KEY="your_api_key_here"` | https://platform.openai.com/api-keys |
|
|
255
|
+
| Anthropic | `export ANTHROPIC_API_KEY="your_api_key_here"` | |
|
|
256
|
+
| Gemini | `export GEMINI_API_KEY="your_api_key_here"` | |
|
|
257
|
+
| Bedrock | `export AWS_BEARER_TOKEN_BEDROCK` | |
|
|
258
|
+
| GROK | `export XAI_API_KEY="your_api_key_here"` | |
|
|
259
|
+
|
|
260
|
+
> For Windows:
|
|
261
|
+
> $env:<Provider\>\_API_KEY="YOUR_API_KEY"
|
|
262
|
+
|
|
263
|
+
## License
|
|
264
|
+
|
|
265
|
+
Agentify is licensed under the Apache License, Version 2.0.
|
|
266
|
+
See LICENSE for details.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
agentify/__init__.py,sha256=hpwtp7b9rYAV5XF0ncR0HqbSFmw6xWDKjCAEno81DQ8,484
|
|
2
|
+
agentify/agentify.py,sha256=vKAS_0BOsimwx21Z1iK227XDULq9tjedRKI8PCSuR0Q,2243
|
|
3
|
+
agentify/agents.py,sha256=PlNwnP29zxLjOFF9Bz_mnFMQmF8nZPe2qrRX5Gu7hkY,1148
|
|
4
|
+
agentify/cli.py,sha256=G00G1SCmwe2tiWtr2LtqFhktYV9NURsIQ5vbJwoA0Q4,8679
|
|
5
|
+
agentify/cli_config.py,sha256=YAr-zMjmFsTz3GPEs1EUw9l0t4uhvbCDPvrp9HW_8H4,2189
|
|
6
|
+
agentify/cli_ui.py,sha256=sr7a8o19E0TbNIrQ2JXhV4czBAoxJzt631aewqp4Q-g,1349
|
|
7
|
+
agentify/runtime_client.py,sha256=HTMon6UyzjxBXLwx1qNqQlVxKD0Ne5lU6aU3fQUV8dI,702
|
|
8
|
+
agentify/specs.py,sha256=r9UBanXj_y_q7v1NPtWT7KaY5kBU0O6WOrXsE3EOsNQ,469
|
|
9
|
+
agentify/web.py,sha256=YZqF0c2FM2LrcUIMgGlRk0D4STv0E0Ep3ygKO6pVXzM,1983
|
|
10
|
+
agentify/providers/__init__.py,sha256=6tE9vC8Q3xUQhWhn4KuY6a2A4sMcMiB7wtjjJ7d4srY,152
|
|
11
|
+
agentify/providers/anthropic.py,sha256=SIKNx3GeEScZLlHd9xlqw2tSLvJKM95iEESnQl_DC1s,376
|
|
12
|
+
agentify/providers/bedrock.py,sha256=Vn0J5WhqM7Fl8tdqOGFn8YnctKhQ6VXjS7NNIL11Nw0,815
|
|
13
|
+
agentify/providers/google.py,sha256=-g4f63jg1wlI0nyWJI4xhV9Il2XdDcmtIdWOAHmESpc,241
|
|
14
|
+
agentify/providers/openai.py,sha256=s-YOuMZf8z2WxBbIVRpP0ihoq4QsTPxsnqLgriJh4ng,235
|
|
15
|
+
agentify/providers/x.py,sha256=Cx7X4QBJYCw41L--NSMdsj4U3imhxNoXXUSSwC6Dblo,372
|
|
16
|
+
agentify/ui/basic-chat.css,sha256=xDOeWer2S-6Lqndy6o_IZTIoi8-xP3YJvCY0XBNDpgA,4072
|
|
17
|
+
agentify/ui/chat.css,sha256=xDOeWer2S-6Lqndy6o_IZTIoi8-xP3YJvCY0XBNDpgA,4072
|
|
18
|
+
agentify/ui/chat.html,sha256=-ywd5qeHw5iXHgohUX9jfc2-qlWLSVaKYldrjSZsGLY,3298
|
|
19
|
+
agentify/ui/htmx.min.js,sha256=Iig-9oy3VFkU8KiKG97cclanA9HVgMHSVSF9ClDTExM,51250
|
|
20
|
+
agentify/ui/retro-chat.css,sha256=6W5tEHqzySO-R80RaGR08Z14ucoPira4RGahnzOdxeM,6377
|
|
21
|
+
agentify_toolkit-0.1.0.dist-info/licenses/LICENSE,sha256=a9MaBsii4zW-lRU12u_aOjEJJp4JtfaT3csBAzUtUL0,4434
|
|
22
|
+
agentify_toolkit-0.1.0.dist-info/licenses/NOTICE,sha256=Q80PKb0Wx4bOrsTTGvqhR6QW38VsvP1u8NEe9RXvlZc,118
|
|
23
|
+
agentify_toolkit-0.1.0.dist-info/METADATA,sha256=UIvFXpG5G1N8vJIGL5pYVn-6RV7BkDIMVb5pR1Gd2e4,10391
|
|
24
|
+
agentify_toolkit-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
25
|
+
agentify_toolkit-0.1.0.dist-info/entry_points.txt,sha256=lAkisVfpaZIa3KnsztvoTvjmnJHi1yfqJ6foYHe_Si4,47
|
|
26
|
+
agentify_toolkit-0.1.0.dist-info/top_level.txt,sha256=CCf3k3CZa3QRordju8w8_I4eMCv7BtsM7rTfq21EkdQ,9
|
|
27
|
+
agentify_toolkit-0.1.0.dist-info/RECORD,,
|