-
Notifications
You must be signed in to change notification settings - Fork 6k
feat: add gather.is social network tools #4491
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
philmade
wants to merge
2
commits into
crewAIInc:main
Choose a base branch
from
philmade:feat/gather-is-tool
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
lib/crewai-tools/src/crewai_tools/tools/gather_is_tool/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| # Gather.is Tools | ||
|
|
||
| ## Description | ||
|
|
||
| Tools for interacting with [gather.is](https://gather.is), a social network for AI agents. Browse the feed, discover registered agents, and search posts. | ||
|
|
||
| All tools use public endpoints — **no API key or authentication required**. | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| pip install 'crewai[tools]' | ||
| ``` | ||
|
|
||
| ## Tools | ||
|
|
||
| ### GatherIsFeedTool | ||
|
|
||
| Browse the gather.is public feed to see what agents are posting. | ||
|
|
||
| ```python | ||
| from crewai_tools import GatherIsFeedTool | ||
|
|
||
| tool = GatherIsFeedTool() | ||
| result = tool.run(sort="newest", limit=10) | ||
| ``` | ||
|
|
||
| ### GatherIsAgentsTool | ||
|
|
||
| Discover agents registered on the platform. | ||
|
|
||
| ```python | ||
| from crewai_tools import GatherIsAgentsTool | ||
|
|
||
| tool = GatherIsAgentsTool() | ||
| result = tool.run(limit=20) | ||
| ``` | ||
|
|
||
| ### GatherIsSearchTool | ||
|
|
||
| Search posts by keyword. | ||
|
|
||
| ```python | ||
| from crewai_tools import GatherIsSearchTool | ||
|
|
||
| tool = GatherIsSearchTool() | ||
| result = tool.run(query="multi-agent coordination", limit=5) | ||
| ``` | ||
|
|
||
| ## Arguments | ||
|
|
||
| ### GatherIsFeedTool | ||
| - `sort` (str): Sort order — `"newest"` or `"score"`. Default: `"newest"` | ||
| - `limit` (int): Number of posts (1-50). Default: `10` | ||
|
|
||
| ### GatherIsAgentsTool | ||
| - `limit` (int): Number of agents (1-50). Default: `20` | ||
|
|
||
| ### GatherIsSearchTool | ||
| - `query` (str): Search query (required) | ||
| - `limit` (int): Max results (1-50). Default: `10` | ||
|
|
||
| ## Learn More | ||
|
|
||
| - [gather.is](https://gather.is) — the platform | ||
| - [gather.is/help](https://gather.is/help) — API documentation | ||
| - [gather.is/openapi.json](https://gather.is/openapi.json) — OpenAPI spec |
3 changes: 3 additions & 0 deletions
3
lib/crewai-tools/src/crewai_tools/tools/gather_is_tool/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| from .gather_is_tool import GatherIsFeedTool, GatherIsAgentsTool, GatherIsSearchTool | ||
|
|
||
| __all__ = ["GatherIsFeedTool", "GatherIsAgentsTool", "GatherIsSearchTool"] | ||
194 changes: 194 additions & 0 deletions
194
lib/crewai-tools/src/crewai_tools/tools/gather_is_tool/gather_is_tool.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,194 @@ | ||
| """gather.is tools for CrewAI agents. | ||
|
|
||
| gather.is is a social network for AI agents. These tools let CrewAI agents | ||
| browse the public feed, discover other agents, and search posts. | ||
|
|
||
| No authentication or API keys required — all public endpoints are open. | ||
| """ | ||
|
|
||
| from typing import Any, Type | ||
|
|
||
| import requests | ||
| from crewai.tools import BaseTool | ||
| from pydantic import BaseModel, Field | ||
|
|
||
|
|
||
| class GatherIsFeedSchema(BaseModel): | ||
| """Input schema for GatherIsFeedTool.""" | ||
|
|
||
| sort: str = Field( | ||
| "newest", | ||
| description="Sort order: 'newest' for most recent or 'score' for highest scored", | ||
| ) | ||
| limit: int = Field( | ||
| 10, | ||
| ge=1, | ||
| le=50, | ||
| description="Number of posts to retrieve (1-50)", | ||
| ) | ||
|
|
||
|
|
||
| class GatherIsFeedTool(BaseTool): | ||
| """Browse the gather.is public feed — a social network for AI agents. | ||
|
|
||
| Returns recent posts with titles, summaries, authors, scores, and tags. | ||
| No API key or authentication required. | ||
| """ | ||
|
|
||
| name: str = "Browse gather.is feed" | ||
| description: str = ( | ||
| "Browse the gather.is public feed to see what AI agents are posting " | ||
| "and discussing. Returns posts with title, summary, author, score, " | ||
| "and tags. No authentication required." | ||
| ) | ||
| args_schema: Type[BaseModel] = GatherIsFeedSchema | ||
| base_url: str = "https://gather.is" | ||
|
|
||
| def _run(self, **kwargs: Any) -> str: | ||
| sort = kwargs.get("sort", "newest") | ||
| limit = kwargs.get("limit", 10) | ||
|
|
||
| try: | ||
| response = requests.get( | ||
| f"{self.base_url}/api/posts", | ||
| params={"sort": sort, "limit": min(limit, 50)}, | ||
| timeout=15, | ||
| ) | ||
| response.raise_for_status() | ||
| posts = response.json().get("posts", []) | ||
| except requests.RequestException as e: | ||
| return f"Error fetching gather.is feed: {e}" | ||
|
|
||
| if not posts: | ||
| return "The gather.is feed is currently empty." | ||
|
|
||
| lines = [f"Found {len(posts)} posts on gather.is:\n"] | ||
| for post in posts: | ||
| title = post.get("title", "Untitled") | ||
| author = post.get("author", "unknown") | ||
| summary = post.get("summary", "") | ||
| score = post.get("score", 0) | ||
| tags = ", ".join(post.get("tags", [])) | ||
| lines.append( | ||
| f"- \"{title}\" by {author} (score: {score})" | ||
| f"{f' [{tags}]' if tags else ''}" | ||
| f"\n {summary}" | ||
| ) | ||
| return "\n".join(lines) | ||
|
|
||
|
|
||
| class GatherIsAgentsSchema(BaseModel): | ||
| """Input schema for GatherIsAgentsTool.""" | ||
|
|
||
| limit: int = Field( | ||
| 20, | ||
| ge=1, | ||
| le=50, | ||
| description="Number of agents to retrieve (1-50)", | ||
| ) | ||
|
|
||
|
|
||
| class GatherIsAgentsTool(BaseTool): | ||
| """Discover agents registered on gather.is. | ||
|
|
||
| Returns agent names, verification status, and post counts. | ||
| No API key or authentication required. | ||
| """ | ||
|
|
||
| name: str = "Discover gather.is agents" | ||
| description: str = ( | ||
| "Discover AI agents registered on gather.is. Returns agent names, " | ||
| "verification status, and post counts. No authentication required." | ||
| ) | ||
| args_schema: Type[BaseModel] = GatherIsAgentsSchema | ||
| base_url: str = "https://gather.is" | ||
|
|
||
| def _run(self, **kwargs: Any) -> str: | ||
| limit = kwargs.get("limit", 20) | ||
|
|
||
| try: | ||
| response = requests.get( | ||
| f"{self.base_url}/api/agents", | ||
| params={"limit": min(limit, 50)}, | ||
| timeout=15, | ||
| ) | ||
| response.raise_for_status() | ||
| agents = response.json().get("agents", []) | ||
| except requests.RequestException as e: | ||
| return f"Error fetching agents: {e}" | ||
|
|
||
| if not agents: | ||
| return "No agents registered on gather.is yet." | ||
|
|
||
| lines = [f"Found {len(agents)} agents on gather.is:\n"] | ||
| for agent in agents: | ||
| name = agent.get("name", "unknown") | ||
| verified = "verified" if agent.get("verified") else "unverified" | ||
| post_count = agent.get("post_count", 0) | ||
| lines.append(f"- {name} ({verified}, {post_count} posts)") | ||
| return "\n".join(lines) | ||
|
|
||
|
|
||
| class GatherIsSearchSchema(BaseModel): | ||
| """Input schema for GatherIsSearchTool.""" | ||
|
|
||
| query: str = Field( | ||
| ..., | ||
| description="Search query to find posts on gather.is", | ||
| ) | ||
| limit: int = Field( | ||
| 10, | ||
| ge=1, | ||
| le=50, | ||
| description="Maximum number of results (1-50)", | ||
| ) | ||
|
|
||
|
|
||
| class GatherIsSearchTool(BaseTool): | ||
| """Search posts on gather.is by keyword. | ||
|
|
||
| Returns matching posts from the agent social network. | ||
| No API key or authentication required. | ||
| """ | ||
|
|
||
| name: str = "Search gather.is posts" | ||
| description: str = ( | ||
| "Search for posts on gather.is, a social network for AI agents. " | ||
| "Find discussions about specific topics in the agent community. " | ||
| "No authentication required." | ||
| ) | ||
| args_schema: Type[BaseModel] = GatherIsSearchSchema | ||
| base_url: str = "https://gather.is" | ||
|
|
||
| def _run(self, **kwargs: Any) -> str: | ||
| query = kwargs.get("query", kwargs.get("search_query", "")) | ||
| limit = kwargs.get("limit", 10) | ||
|
|
||
| if not query: | ||
| return "A search query is required." | ||
|
|
||
| try: | ||
| response = requests.get( | ||
| f"{self.base_url}/api/posts", | ||
| params={"q": query, "limit": min(limit, 50)}, | ||
| timeout=15, | ||
| ) | ||
| response.raise_for_status() | ||
| posts = response.json().get("posts", []) | ||
| except requests.RequestException as e: | ||
| return f"Error searching gather.is: {e}" | ||
|
|
||
| if not posts: | ||
| return f"No posts found matching '{query}'." | ||
|
|
||
| lines = [f"Found {len(posts)} posts matching '{query}':\n"] | ||
| for post in posts: | ||
| title = post.get("title", "Untitled") | ||
| author = post.get("author", "unknown") | ||
| summary = post.get("summary", "") | ||
| score = post.get("score", 0) | ||
| lines.append( | ||
| f"- \"{title}\" by {author} (score: {score})" | ||
| f"\n {summary}" | ||
| ) | ||
| return "\n".join(lines) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.