Skip to content

Commit

Permalink
Merge pull request #92 from autonomys/agent-framework
Browse files Browse the repository at this point in the history
Add Auto agent framework
  • Loading branch information
Xm0onh authored Jan 2, 2025
2 parents e2d0ae1 + 2cab0c8 commit 18a08c4
Show file tree
Hide file tree
Showing 38 changed files with 4,278 additions and 0 deletions.
38 changes: 38 additions & 0 deletions auto-agents-framework/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Twitter Credentials
TWITTER_USERNAME=<twitter_username>
TWITTER_PASSWORD=<twitter_password>

# Twitter data fetch and post configuration
NUM_TIMELINE_TWEETS=10
NUM_FOLLOWING_RECENT_TWEETS=10
NUM_RANDOM_FOLLOWERS=5
MAX_MENTIONS=20
MAX_THREAD_LENGTH=20
MAX_MY_RECENT_TWEETS=10
POST_TWEETS=false
RESPONSE_INTERVAL_MINUTES=26
POST_INTERVAL_MINUTES=30

# AutoDrive Configuration
AUTO_DRIVE_API_KEY=<auto_drive_api_key>
AUTO_DRIVE_ENCRYPTION_PASSWORD=<auto_drive_encryption_password>
AUTO_DRIVE_UPLOAD=false

# SC Configuration
RPC_URL=<rpc_url>
CONTRACT_ADDRESS=<contract_address>
PRIVATE_KEY=<private_key>

# LLM Configuration
SMALL_LLM_MODEL=gpt-4o-mini
LARGE_LLM_MODEL=<large_llm_model>
OPENAI_API_KEY=<openai_api_key>

# SerpAPI Configuration
SERPAPI_API_KEY=<serpapi_api_key>

# Server Configuration
PORT=<port>

# Environment
NODE_ENV=<node_env>
1 change: 1 addition & 0 deletions auto-agents-framework/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
character.ts
10 changes: 10 additions & 0 deletions auto-agents-framework/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"semi": true,
"trailingComma": "all",
"singleQuote": true,
"quoteProps": "as-needed",
"jsxSingleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"arrowParens": "avoid"
}
88 changes: 88 additions & 0 deletions auto-agents-framework/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Auto-Agents-Framework: Framework for building AI agents

Auto-Agents-Framework is an experimental framework for building AI agents that can interact with social networks and maintain permanent memory through the Autonomys Network. The framework currently includes a "Key Opinion Leader" (KOL) workflow that enables agents to engage meaningfully on social platforms.

## Features

- 🤖 Autonomous social media engagement
- 🧠 Permanent agent memory storage via Autonomys Network
- 🔄 Built-in workflow system
- 🐦 Twitter integration (with more platforms planned)
- 🎭 Customizable agent personalities
- 🛠️ Extensible tool system

## Getting Started

1. Install dependencies:
`yarn install`

2. Copy the environment file and configure your credentials:
`cp .env.sample .env`

3. Create your agent character by copying the example:
`cp src/agents/workflows/kol/characters/character.example.ts src/agents/workflows/kol/characters/character.ts`

4. Configure your character:

```
// character.ts
const name = 'Your Agent Name';
const username = 'twitter_handle';
const walletAddress = '0x...'; // Your Autonomys Network wallet
const description = 'Your agent's personality description...';
// Configure additional personality traits, expertise, rules, etc.
```

## Character Configuration

The character configuration defines your agent's personality and behavior. Key sections include:

- `description`: Core personality and background
- `personality`: Key behavioral traits
- `expertise`: Areas of knowledge
- `rules`: Operating guidelines
- `trendFocus`: Topics to monitor
- `contentFocus`: Content creation guidelines
- `replyStyle`: Engagement approach
- `wordsToAvoid`: Restricted vocabulary

## Autonomys Network Integration

The framework uses the Autonomys Network for permanent storage of agent memory and interactions. This enables:

- Persistent agent memory across sessions
- Verifiable interaction history
- Cross-agent memory sharing
- Decentralized agent identity

To use this feature:

1. Configure your Autonomys Network credentials in `.env`
2. Set `AUTO_DRIVE_UPLOAD=true`
3. Provide your wallet details and encryption password

## Workflows

### KOL (Key Opinion Leader)

The KOL workflow enables agents to:

- Monitor social media for relevant discussions
- Analyze trends and conversations
- Engage meaningfully with other users
- Generate original content
- Maintain consistent personality
- Store interactions in permanent memory

## Running the Agent

Start the agent with:
`yarn dev`

Monitor the agent's activity in the console and configured log files.

## License

MIT
62 changes: 62 additions & 0 deletions auto-agents-framework/examples/twitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { TwitterApi } from '../src/services/twitter/types.js';
import { createTwitterApi } from '../src/services/twitter/client.js';
import { config } from '../src/config/index.js';
import { createLogger } from '../src/utils/logger.js';
import { SearchMode, Scraper, Tweet } from 'agent-twitter-client';

const logger = createLogger('twitter', './examples/logs');

const { USERNAME, PASSWORD, COOKIES_PATH } = config.twitterConfig;

const twitterApi: TwitterApi = await createTwitterApi(USERNAME, PASSWORD, COOKIES_PATH);
const { scraper } = twitterApi;
// const myMentions = await twitterApi.getMyMentions(5);
// logger.info('My Mentions', { myMentions });

const iterateResponse = async <T>(response: AsyncGenerator<T>): Promise<T[]> => {
const tweets: T[] = [];
for await (const tweet of response) {
tweets.push(tweet);
}
return tweets;
};

const myMentions = await twitterApi.getMyUnrepliedToMentions(5);
logger.info('My Mentions', { myMentions });


const conversationId = '1874032422175858869';
const tweetId = '1874146661251113110';

// const conversation = await iterateResponse(
// scraper.searchTweets(`conversation_id:${conversationId}`, 100, SearchMode.Latest),
// );
// const tweet = await scraper.getTweet(tweetId);
// logger.info('Conversation', {
// tweet: {
// text: tweet!.text,
// conversationId: tweet!.conversationId,
// inReplyToStatusId: tweet!.inReplyToStatusId,
// id: tweet!.id,
// },
// conversation: conversation.map(t => ({
// text: t.text,
// username: t.username,
// conversationId: t.conversationId,
// id: t.id,
// })),
// });

// const conversationWithReplies = await iterateResponse(scraper.searchTweets(`to:${twitterApi.username} conversation_id:${conversationId}`, 100, SearchMode.Latest));
// logger.info('Conversation With Replies', { conversationWithReplies: conversationWithReplies.map(t => ({
// text: t.text,
// username: t.username,
// conversationId: t.conversationId,
// id: t.id,
// })),
// });


//logger.info('Conversation', { conversation });

//const myMentions = await twitterApi.getMyUnrepliedToMentions(5);
36 changes: 36 additions & 0 deletions auto-agents-framework/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "auto-agents-framework",
"version": "0.0.1",
"description": "Auto Agents Framework",
"main": "dist/index.js",
"type": "module",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts",
"format": "prettier --write \"src/**/*.ts\"",
"format:check": "prettier --check \"src/**/*.ts\"",
"example:twitter": "tsx examples/twitter.ts"
},
"dependencies": {
"@autonomys/auto-dag-data": "1.2.1",
"@autonomys/auto-drive": "1.2.1",
"@langchain/community": "0.3.20",
"@langchain/core": "0.3.19",
"@langchain/langgraph": "0.2.36",
"@langchain/openai": "0.3.16",
"agent-twitter-client": "0.0.18",
"dotenv": "^16.3.1",
"ethers": "^6.13.4",
"winston": "^3.11.0",
"zod": "^3.22.4"
},
"devDependencies": {
"@tsconfig/node20": "^20.1.4",
"@types/node": "22.10.0",
"@types/sqlite3": "^3.1.11",
"prettier": "^3.2.2",
"tsx": "^4.7.1",
"typescript": "^5.3.3"
}
}
51 changes: 51 additions & 0 deletions auto-agents-framework/src/agents/tools/fetchMentionsTool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { DynamicStructuredTool } from '@langchain/core/tools';
import { z } from 'zod';
import { createLogger } from '../../utils/logger.js';
import { TwitterApi } from '../../services/twitter/types.js';
import { ToolNode } from '@langchain/langgraph/prebuilt';
import { AIMessage } from '@langchain/core/messages';

const logger = createLogger('fetch-mentions-tool');

export const createFetchMentionsTool = (twitterApi: TwitterApi) =>
new DynamicStructuredTool({
name: 'fetch_mentions',
description: 'Fetch recent mentions',
schema: z.object({ maxMentions: z.number(), sinceId: z.string().optional() }),
func: async ({ maxMentions, sinceId }: { maxMentions: number; sinceId?: string }) => {
try {
const recentMentions = await twitterApi.getMyUnrepliedToMentions(maxMentions, sinceId);

return {
tweets: recentMentions,
};
} catch (error) {
logger.error('Error in fetchTimelineTool:', error);
return {
tweets: [],
};
}
},
});

export const invokeFetchMentionsTool = async (
toolNode: ToolNode,
{ maxMentions, sinceId }: { maxMentions: number; sinceId?: string },
) => {
const toolResponse = await toolNode.invoke({
messages: [
new AIMessage({
content: '',
tool_calls: [
{
name: 'fetch_mentions',
args: { maxMentions, sinceId },
id: 'fetch_mentions_call',
type: 'tool_call',
},
],
}),
],
});
return toolResponse;
};
58 changes: 58 additions & 0 deletions auto-agents-framework/src/agents/tools/fetchMyRecentTweetsTool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { DynamicStructuredTool } from '@langchain/core/tools';
import { z } from 'zod';
import { createLogger } from '../../utils/logger.js';
import { TwitterApi } from '../../services/twitter/types.js';
import { ToolNode } from '@langchain/langgraph/prebuilt';
import { AIMessage } from '@langchain/core/messages';

const logger = createLogger('fetch-recent-tweets-tool');

export const createFetchMyRecentTweetsTool = (twitterApi: TwitterApi) =>
new DynamicStructuredTool({
name: 'fetch_my_recent_tweets',
description: 'Fetch the agents recent tweets',
schema: z.object({ maxMyRecentTweets: z.number() }),
func: async ({ maxMyRecentTweets }: { maxMyRecentTweets: number }) => {
try {
const myRecentTweets = await twitterApi.getMyRecentTweets(maxMyRecentTweets);
const repliedToTweetIds = await twitterApi.getMyRepliedToIds();
logger.info('Fetch My Recent Tweets Tool - Result', {
tweets: myRecentTweets.length,
repliedToTweetIds: repliedToTweetIds.length,
});

return {
tweets: myRecentTweets,
repliedToTweetIds: repliedToTweetIds,
};
} catch (error) {
logger.error('Error in fetchRecentTweetsTool:', error);
return {
tweets: [],
repliedToTweetIds: [],
};
}
},
});

export const invokeFetchMyRecentTweetsTool = async (
toolNode: ToolNode,
{ maxMyRecentTweets }: { maxMyRecentTweets: number },
) => {
const toolResponse = await toolNode.invoke({
messages: [
new AIMessage({
content: '',
tool_calls: [
{
name: 'fetch_my_recent_tweets',
args: { maxMyRecentTweets },
id: 'fetch_my_recent_tweets_call',
type: 'tool_call',
},
],
}),
],
});
return toolResponse;
};
Loading

0 comments on commit 18a08c4

Please sign in to comment.