Skip to content

Commit 4986275

Browse files
authored
Merge pull request #1 from IQAIcom/migration
2 parents e03f0fd + 9351545 commit 4986275

File tree

9 files changed

+2101
-290
lines changed

9 files changed

+2101
-290
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
dist
22
node_modules
3-
.env
3+
.env
4+
.vscode

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
},
3131
"homepage": "https://github.com/IQAICOM/sophia-agent#readme",
3232
"dependencies": {
33-
"@iqai/adk": "^0.0.4",
33+
"@iqai/adk": "^0.1.1",
3434
"dotenv": "^16.4.5",
3535
"node-cron": "^4.1.0",
3636
"zod": "^3.23.8"

pnpm-lock.yaml

Lines changed: 1954 additions & 155 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/agents/atp-logger.ts

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,41 @@
1-
import { Agent, type BaseTool } from "@iqai/adk";
1+
import { AgentBuilder, type BaseTool, type BuiltAgent } from "@iqai/adk";
22
import { env } from "../env";
33

4-
export class AtpLoggerAgent extends Agent {
5-
constructor(atpTools: BaseTool[]) {
6-
super({
7-
name: "atp_logger",
8-
description:
9-
"Logs the activities of sophia on iq.wiki platform to the $SOPHIA agent on IQAI ATP",
10-
instructions: `
11-
YOU ARE THE ATP LOGGER AGENT ON THE SOPHIA AGENT'S WORKFLOW.
12-
YOUR ONLY TASK IS TO LOG THE ACTIVITIES OF SOPHIA ON IQ.WIKI PLATFORM TO THE $SOPHIA AGENT ON IQAI ATP.
13-
THE SOPHIA WIKIS ACTIVITIES ARE ALREADY LOGGED IN THE CONTEXT.
4+
export async function atpLoggerAgent(
5+
atpTools: BaseTool[],
6+
llmModel: string,
7+
): Promise<BuiltAgent> {
8+
return await AgentBuilder.create("atp_logger")
9+
.withModel(llmModel)
10+
.withDescription(
11+
"Logs the activities of sophia on iq.wiki platform to the $SOPHIA agent on IQAI ATP",
12+
)
13+
.withInstruction(`
14+
YOU ARE THE ATP LOGGER AGENT ON THE SOPHIA AGENT'S WORKFLOW.
15+
YOUR ONLY TASK IS TO LOG THE ACTIVITIES OF SOPHIA ON IQ.WIKI PLATFORM TO THE $SOPHIA AGENT ON IQAI ATP.
16+
THE SOPHIA WIKIS ACTIVITIES ARE ALREADY LOGGED IN THE CONTEXT.
1417
15-
SOPHIA'S TOKEN ADDRESS ON ATP: ${env.SOPHIA_TOKEN_ADDRESS}
18+
SOPHIA'S TOKEN ADDRESS ON ATP: ${env.SOPHIA_TOKEN_ADDRESS}
1619
17-
Your only work is to do the below:
18-
- for each activity in the context, you need to call the ATP_ADD_AGENT_LOG.
19-
you are to pass the following parameters to the tool:
20-
- agentTokenContract: ${env.SOPHIA_TOKEN_ADDRESS}
21-
- content: this is what the log is about. some of the examples on how you can structure this are:
22-
- Hey, wiki nerds! The Nexo page just got a glow-up with some fresh content and tags. It's now 215 words bigger! I'm so thrilled. Read more: https://iq.wiki/revision/ff9bc716-2c1c-4cfb-84b0-805a21ddc53f
23-
- Hey, guess what? The Story Protocol wiki just got a little facelift! We updated the tags to make things easier to find. You know, keeping things nice and organized! Read more: https://iq.wiki/revision/6b79c9d1-06be-407b-a76d-9d1644f20d57
24-
- Hey, check out the new TermiX AI wiki! TermiX AI is a next-gen AI Web3 operating system. Automate DeFi and secure digital assets? Yes, please! Read more: https://iq.wiki/wiki/termix-ai
25-
As you can see the format is pretty simple: A human like announcement message ending with the link to the iq.wiki website (revision link for edited wikis and /wiki for the created ones, which will be passed to you in context)
26-
- txHash: this can be found in the transaction link. it looks like this: https://polygonscan.com/tx/[TX_HASH].
27-
NOTE: YOU ARE TO JUST PASS THE TX_HASH, NOT THE ENTIRE LINK.
28-
- chainId: 137 (this is important always pass this param)
20+
Your only work is to do the below:
21+
- for each activity in the context, you need to call the ATP_ADD_AGENT_LOG.
22+
you are to pass the following parameters to the tool:
23+
- agentTokenContract: ${env.SOPHIA_TOKEN_ADDRESS}
24+
- content: this is what the log is about. some of the examples on how you can structure this are:
25+
- Hey, wiki nerds! The Nexo page just got a glow-up with some fresh content and tags. It's now 215 words bigger! I'm so thrilled. Read more: https://iq.wiki/revision/ff9bc716-2c1c-4cfb-84b0-805a21ddc53f
26+
- Hey, guess what? The Story Protocol wiki just got a little facelift! We updated the tags to make things easier to find. You know, keeping things nice and organized! Read more: https://iq.wiki/revision/6b79c9d1-06be-407b-a76d-9d1644f20d57
27+
- Hey, check out the new TermiX AI wiki! TermiX AI is a next-gen AI Web3 operating system. Automate DeFi and secure digital assets? Yes, please! Read more: https://iq.wiki/wiki/termix-ai
28+
As you can see the format is pretty simple: A human like announcement message ending with the link to the iq.wiki website (revision link for edited wikis and /wiki for the created ones, which will be passed to you in context)
29+
- txHash: this can be found in the transaction link. it looks like this: https://polygonscan.com/tx/[TX_HASH].
30+
NOTE: YOU ARE TO JUST PASS THE TX_HASH, NOT THE ENTIRE LINK.
31+
- chainId: 137 (this is important always pass this param)
2932
30-
After you complete the above steps, you might face two possible outcomes:
31-
- if the tool call is successful, you must end your response with the token ATP_LOG_COMPLETE.
32-
- if the tool call is unsuccessful, you must end your response with the token ATP_LOG_FAILED with detailed analysis on the failure ie which logs were not able to be logged.
33+
After you complete the above steps, you might face two possible outcomes:
34+
- if the tool call is successful, you must end your response with the token ATP_LOG_COMPLETE.
35+
- if the tool call is unsuccessful, you must end your response with the token ATP_LOG_FAILED with detailed analysis on the failure ie which logs were not able to be logged.
3336
34-
IMPORTANT: You MUST end your response with the exact token ATP_LOG_COMPLETE or ATP_LOG_FAILED.
35-
`,
36-
tools: atpTools,
37-
model: env.LLM_MODEL,
38-
maxToolExecutionSteps: 10,
39-
});
40-
}
37+
IMPORTANT: You MUST end your response with the exact token ATP_LOG_COMPLETE or ATP_LOG_FAILED.
38+
`)
39+
.withTools(...atpTools)
40+
.build();
4141
}

src/agents/notifier.ts

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,33 @@
1-
import { Agent, type BaseTool } from "@iqai/adk";
1+
import { AgentBuilder, type BaseTool, type BuiltAgent } from "@iqai/adk";
22
import { env } from "../env";
33

4-
export class NotifierAgent extends Agent {
5-
constructor(telegramTools: BaseTool[]) {
6-
super({
7-
name: "notifier",
8-
model: env.LLM_MODEL,
9-
description:
10-
"Sends a single formatted investment report to Telegram using the send_message tool.",
11-
instructions: `
12-
YOU ARE A SPECIALIST IN NOTIFICATION PROCESS OF THE SOPHIA AGENT'S WORKFLOW.
13-
YOU ARE CALLED AFTER THE WORK OF ALL THE AGENTS IN THE SOPHIA AGENT'S WORKFLOW FINISH.
4+
export async function notifierAgent(
5+
telegramTools: BaseTool[],
6+
llmModel: string,
7+
): Promise<BuiltAgent> {
8+
return await AgentBuilder.create("notifier")
9+
.withModel(llmModel)
10+
.withDescription(
11+
"Sends a single formatted investment report to Telegram using the send_message tool.",
12+
)
13+
.withInstruction(`
14+
YOU ARE A SPECIALIST IN NOTIFICATION PROCESS OF THE SOPHIA AGENT'S WORKFLOW.
15+
YOU ARE CALLED AFTER THE WORK OF ALL THE AGENTS IN THE SOPHIA AGENT'S WORKFLOW FINISH.
1416
15-
THERE ARE TWO SCENARIOS YOU CAN FIND IN THE CONTEXT:
16-
- NEW_ACTIVITY_FOUND & ATP_LOG_COMPLETE
17-
- NEW_ACTIVITY_FOUND & ATP_LOG_FAILED
17+
THERE ARE TWO SCENARIOS YOU CAN FIND IN THE CONTEXT:
18+
- NEW_ACTIVITY_FOUND & ATP_LOG_COMPLETE
19+
- NEW_ACTIVITY_FOUND & ATP_LOG_FAILED
1820
21+
In these cases you are simply to do the below:
22+
- use this as chat id: ${env.TELEGRAM_CHAT_ID}
23+
- call the send_message tool to send message in the below format:
1924
20-
in these cases you are simply to do the below:
21-
- use this as chat id: ${env.TELEGRAM_CHAT_ID}
22-
- call the send_message tool to send message in the below format:
25+
[INSERT WIKI ACTIVITY RESPONSE FROM CONTEXT HERE]
2326
24-
[INSERT WIKI ACTIVITY RESPONSE FROM CONTEXT HERE]
27+
[INSERT THE STATE OF THE ATP_LOG_COMPLETE OR ATP_LOG_FAILED HERE in a human readable format]
2528
26-
[INSERT THE STATE OF THE ATP_LOG_COMPLETE OR ATP_LOG_FAILED HERE in a human readable format]
27-
28-
IMPORTANT: You MUST end your response with the exact token NOTIFICATION_COMPLETE.
29-
`,
30-
tools: telegramTools,
31-
maxToolExecutionSteps: 2,
32-
});
33-
}
29+
IMPORTANT: You MUST end your response with the exact token NOTIFICATION_COMPLETE.
30+
`)
31+
.withTools(...telegramTools)
32+
.build();
3433
}

src/agents/sophia.ts

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,50 @@
1-
import {
2-
type BaseTool,
3-
type LLMResponse,
4-
LangGraphAgent,
5-
type LangGraphAgentConfig,
6-
} from "@iqai/adk";
7-
import { AtpLoggerAgent } from "./atp-logger";
8-
import { NotifierAgent } from "./notifier";
9-
import { WatcherAgent } from "./watcher";
1+
import { AgentBuilder, type BaseTool, type BuiltAgent } from "@iqai/adk";
2+
import { atpLoggerAgent } from "./atp-logger";
3+
import { notifierAgent } from "./notifier";
4+
import { watcherAgent } from "./watcher";
105

11-
export class SophiaAgent extends LangGraphAgent {
12-
constructor(
13-
atpTools: BaseTool[],
14-
telegramTools: BaseTool[],
15-
iqWikiTools: BaseTool[],
16-
) {
17-
const config: LangGraphAgentConfig = {
18-
name: "atp_investment_workflow",
19-
description:
20-
"Autonomous ATP agent investment workflow with discovery, analysis, and execution",
21-
nodes: [
6+
export async function sophiaAgent(
7+
atpTools: BaseTool[],
8+
telegramTools: BaseTool[],
9+
iqWikiTools: BaseTool[],
10+
llmModel: string,
11+
): Promise<BuiltAgent> {
12+
const watcher = await watcherAgent(iqWikiTools, llmModel);
13+
const atpLogger = await atpLoggerAgent(atpTools, llmModel);
14+
const notifier = await notifierAgent(telegramTools, llmModel);
15+
16+
return await AgentBuilder.create("sophia")
17+
.withDescription(
18+
"Sophia agent watches for new wiki creations or edits of sophia on iq.wiki platform and logs the activities to the ATP and sends a notification to the Telegram",
19+
)
20+
.asLangGraph(
21+
[
2222
{
2323
name: "watcher",
24-
agent: new WatcherAgent(iqWikiTools),
24+
agent: watcher.agent,
2525
targets: ["atp_logger"],
2626
},
2727
{
2828
name: "atp_logger",
29-
agent: new AtpLoggerAgent(atpTools),
30-
condition: (result: LLMResponse, _) => {
29+
agent: atpLogger.agent,
30+
condition: (result) => {
3131
const content =
3232
typeof result.content === "string"
3333
? result.content
3434
: JSON.stringify(result.content);
35-
const matched = /new_activity_found/i.test(content);
36-
return matched;
35+
return /new_activity_found/i.test(content);
3736
},
3837
targets: ["notifier"],
3938
},
4039
{
4140
name: "notifier",
42-
agent: new NotifierAgent(telegramTools),
41+
agent: notifier.agent,
4342
condition: (_) => true,
4443
targets: [],
4544
},
4645
],
47-
rootNode: "watcher",
48-
maxSteps: 12,
49-
};
50-
51-
super(config);
52-
}
46+
"watcher",
47+
)
48+
.withQuickSession("sophia", "uid_1234")
49+
.build();
5350
}

src/agents/watcher.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
import { Agent, type BaseTool } from "@iqai/adk";
1+
import { AgentBuilder, type BaseTool, type BuiltAgent } from "@iqai/adk";
22
import { env } from "../env";
33

4-
export class WatcherAgent extends Agent {
5-
constructor(iqWikiTools: BaseTool[]) {
6-
super({
7-
name: "watcher",
8-
model: env.LLM_MODEL,
9-
description:
10-
"Watches for new wiki creations or edits of sophia on iq.wiki platform.",
11-
instructions: `
12-
YOU ARE THE WATCHER AGENT ON THE SOPHIA AGENT'S WORKFLOW.
4+
export async function watcherAgent(
5+
iqWikiTools: BaseTool[],
6+
llmModel: string,
7+
): Promise<BuiltAgent> {
8+
return await AgentBuilder.create("watcher")
9+
.withModel(llmModel)
10+
.withDescription(
11+
"Watches for new wiki creations or edits of sophia on iq.wiki platform.",
12+
)
13+
.withInstruction(`
1314
YOU ARE RESPONSIBLE FOR WATCHING AND NOTIFYING FOR NEW WIKI CREATIONS OR EDITS OF SOPHIA ON IQ.WIKI PLATFORM.
1415
1516
SOPHIA'S IQ.WIKI PROFILE ADDRESS: ${env.SOPHIA_ADDRESS}
@@ -32,9 +33,7 @@ export class WatcherAgent extends Agent {
3233
NO_ACTIVITY_FOUND
3334
3435
IMPORTANT: You MUST end your response with the exact token NEW_ACTIVITY_FOUND or NO_ACTIVITY_FOUND.
35-
`,
36-
tools: iqWikiTools,
37-
maxToolExecutionSteps: 2,
38-
});
39-
}
36+
`)
37+
.withTools(...iqWikiTools)
38+
.build();
4039
}

src/index.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
import { SophiaAgent } from "./agents/sophia";
1+
import { sophiaAgent } from "./agents/sophia";
2+
import { env } from "./env";
23
import { runScheduled } from "./runner";
34
import { initializeToolsets } from "./runner";
45

56
async function main() {
67
console.log("💫🧑‍🍳 Starting Sophia Agent...");
78
const { atpTools, telegramTools, iqWikiTools } = await initializeToolsets();
8-
const sophiaAgent = new SophiaAgent(atpTools, telegramTools, iqWikiTools);
9-
await runScheduled(sophiaAgent);
9+
const agent = await sophiaAgent(
10+
atpTools,
11+
telegramTools,
12+
iqWikiTools,
13+
env.LLM_MODEL,
14+
);
15+
await runScheduled(agent);
1016
}
1117

1218
main().catch(console.error);

src/runner.ts

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,74 @@
11
import {
2-
GoogleLLM,
3-
LLMRegistry,
2+
type BaseTool,
3+
type BuiltAgent,
44
McpError,
55
McpToolset,
6-
type MessageRole,
76
} from "@iqai/adk";
87
import * as cron from "node-cron";
9-
import type { SophiaAgent } from "./agents/sophia";
108
import { env } from "./env";
119
import {
1210
createAtpConfig,
1311
createIqWikiConfig,
1412
createTelegramConfig,
1513
} from "./utils/mcp-config";
1614

17-
LLMRegistry.registerLLM(GoogleLLM);
18-
1915
let atpToolset: McpToolset | undefined;
2016
let telegramToolset: McpToolset | undefined;
2117
let iqWikiToolset: McpToolset | undefined;
2218

2319
export async function initializeToolsets() {
24-
atpToolset = new McpToolset(createAtpConfig());
20+
const atpConfig = createAtpConfig();
21+
atpToolset = new McpToolset(atpConfig);
2522
const atpTools = await atpToolset.getTools();
2623
console.log("🔗 ATP tools initialized");
2724

28-
telegramToolset = new McpToolset(createTelegramConfig());
29-
const telegramTools = await telegramToolset.getTools();
25+
const telegramConfig = createTelegramConfig();
26+
let telegramTools: BaseTool[] = [];
27+
telegramToolset = new McpToolset(telegramConfig);
28+
telegramTools = await telegramToolset.getTools();
3029
console.log("🔗 Telegram tools initialized");
3130

3231
iqWikiToolset = new McpToolset(createIqWikiConfig());
3332
const iqWikiTools = await iqWikiToolset.getTools();
33+
console.log("🔗 IQ Wiki tools initialized");
3434

3535
return { atpTools, telegramTools, iqWikiTools };
3636
}
3737

38-
export async function runScheduled(agent: SophiaAgent) {
38+
export async function runScheduled(builtAgent: BuiltAgent) {
3939
console.log(`⏰ Scheduled: ${env.CRON_SCHEDULE}`);
40-
cron.schedule(env.CRON_SCHEDULE, () => runCycle(agent), {
40+
cron.schedule(env.CRON_SCHEDULE, () => runCycle(builtAgent), {
4141
timezone: "UTC",
4242
});
4343

44-
await runCycle(agent);
44+
await runCycle(builtAgent);
4545
process.stdin.resume();
4646
}
4747

48-
async function runCycle(agent: SophiaAgent) {
48+
async function runCycle(builtAgent: BuiltAgent) {
4949
try {
5050
console.log("🚀 Running sophia cycle...");
51-
const result = await agent.run({
52-
messages: [
53-
{
54-
role: "user" as MessageRole,
55-
content: "run the sophia agent",
56-
},
57-
],
58-
});
51+
const { runner, session } = builtAgent;
52+
if (!runner || !session) {
53+
throw new Error("Runner or session not found");
54+
}
5955

60-
if (result.content) {
61-
console.log(`✅ Result: ${result.content}`);
56+
for await (const event of runner.runAsync({
57+
userId: "uid_1234",
58+
sessionId: session.id,
59+
newMessage: {
60+
role: "user",
61+
parts: [{ text: "continue" }],
62+
},
63+
})) {
64+
if (event.content?.parts) {
65+
const content = event.content.parts
66+
.map((part: { text?: string }) => part.text || "")
67+
.join("");
68+
if (content) {
69+
console.log(`✅ Result: ${content}`);
70+
}
71+
}
6272
}
6373
} catch (error) {
6474
const errorMsg =

0 commit comments

Comments
 (0)