Skip to content
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

Feature branch farcaster support #71

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from cdp_agentkit_core.actions.social.farcaster.action import FarcasterAction
from cdp_agentkit_core.actions.social.farcaster.cast import CastAction
from cdp_agentkit_core.actions.social.farcaster.user_details import UserDetailsAction
from cdp_agentkit_core.actions.social.farcaster.notifications import NotificationsAction

def get_all_farcaster_actions() -> list[FarcasterAction]:
"""Get all Farcaster actions."""
actions = []
for action in FarcasterAction.__subclasses__():
actions.append(action())
return actions


FARCASTER_ACTIONS = get_all_farcaster_actions()

__all__ = [
"FARCASTER_ACTIONS",
"FarcasterAction",
"CastAction",
"UserDetailsAction",
"NotificationsAction",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from collections.abc import Callable
from typing import Optional, Type

from pydantic import BaseModel

class FarcasterAction(BaseModel):
"""Farcaster Action Base Class."""

name: str
description: str
args_schema: Optional[Type[BaseModel]] = None
func: Callable[..., str]

class Config:
"""Pydantic config."""
arbitrary_types_allowed = True
extra = "forbid"
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from typing import List, Optional
from pydantic import BaseModel, Field, ConfigDict
from cdp_agentkit_core.actions.social.farcaster.action import FarcasterAction


class CastInput(BaseModel):
"""Input for casting to Farcaster."""
model_config = ConfigDict(extra="forbid")
text: str = Field(..., description="The text content to cast")
channel_id: Optional[str] = Field(None, description="Optional channel to post in")
embeds: Optional[List[str]] = Field(None, description="Optional list of URLs to embed")


class CastAction(FarcasterAction):
"""Farcaster cast action."""

name: str = "cast"
description: str = """
Use this tool to post a cast (message) to Farcaster.
Input should be the text you want to cast.
You can also specify a channel_id for posting in a specific channel,
and embeds for including URLs.
"""
args_schema: type[BaseModel] = CastInput
func = lambda client, text, channel_id=None, embeds=None: client.cast(text=text, channel_id=channel_id, embeds=embeds)


# FARCASTER_ACTIONS = [CastAction()]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# FARCASTER_ACTIONS = [CastAction()]

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from typing import List, Optional
from pydantic import BaseModel, Field, ConfigDict
from cdp_agentkit_core.actions.social.farcaster.action import FarcasterAction


class NotificationsInput(BaseModel):
"""Input for getting Farcaster notifications."""
model_config = ConfigDict(extra="forbid")

types: Optional[List[str]] = Field(
None,
description="Optional list of notification types to fetch (follows, recasts, likes, mentions, replies)"
)
fid: Optional[str] = Field(
None,
description="The FID of the user to get notifications for. If not provided, uses the authenticated user's FID."
)


class NotificationsAction(FarcasterAction):
"""Farcaster notifications action."""

name: str = "notifications"
description: str = """
Get notifications for a Farcaster user.
If no FID is provided, it will show notifications for your own account.
You can specify types of notifications to fetch (follows, recasts, likes, mentions, replies).
If no types are specified, all types will be fetched.

Examples:
- "Show my notifications"
- "Check my mentions"
- "Show my recent replies"
"""
args_schema: type[BaseModel] = NotificationsInput
func = lambda client, types=None, fid=None: client.get_notifications(fid, types)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from pydantic import BaseModel, Field, ConfigDict
from cdp_agentkit_core.actions.social.farcaster.action import FarcasterAction
from typing import Optional


class UserDetailsInput(BaseModel):
"""Input argument schema for Farcaster user details action."""
model_config = ConfigDict(extra="forbid")

fid: Optional[str] = Field(
None,
description="The FID (Farcaster ID) of the user to get details for. If not provided, uses the authenticated user's FID."
)


class UserDetailsAction(FarcasterAction):
"""Farcaster user details action."""

name: str = "user_details"
description: str = """
This tool will return user details for a Farcaster user.
If no FID is provided, it will return details for your own account.

Input:
- fid (optional): The FID of another user you want to look up
"""
args_schema: type[BaseModel] = UserDetailsInput
func = lambda client, fid=None: client.get_user_details(fid)
23 changes: 23 additions & 0 deletions farcaster-langchain/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.PHONY: format
format:
ruff format .

.PHONY: lint
lint:
ruff check .

.PHONY: lint-fix
lint-fix:
ruff check . --fix

.PHONY: docs
docs:
sphinx-apidoc -f -o ./docs ./farcaster_langchain

.PHONY: local-docs
local-docs: docs
cd docs && make html && open ./_build/html/index.html

.PHONY: test
test:
pytest
132 changes: 132 additions & 0 deletions farcaster-langchain/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Farcaster Langchain Toolkit
Farcaster integration with Langchain to enable agentic workflows using the core primitives defined in `cdp-agentkit-core`.

This toolkit contains tools that enable an LLM agent to interact with [Farcaster](https://www.farcaster.xyz/) via the [Neynar API](https://docs.neynar.com/). The toolkit provides a wrapper around the Neynar API, allowing agents to perform social operations like posting casts and replies.

## Setup

### Prerequisites
- Python 3.10 or higher
- [OpenAI API Key](https://platform.openai.com/api-keys)
- [Neynar API Key](https://docs.neynar.com/reference/getting-started)
- [Neynar Signer UUID](https://docs.neynar.com/reference/create-signer)
- Farcaster Account with FID

### Installation

```bash
pip install farcaster-langchain
```

### Environment Setup

Set the following environment variables:

```bash
export OPENAI_API_KEY=<your-openai-api-key>
export NEYNAR_API_KEY=<your-neynar-api-key>
export NEYNAR_SIGNER_UUID=<your-signer-uuid>
export FARCASTER_FID=<your-farcaster-id>
```

## Usage

### Basic Setup

```python
from farcaster_langchain import (
FarcasterApiWrapper,
FarcasterToolkit
)

# Initialize FarcasterApiWrapper
farcaster_api_wrapper = FarcasterApiWrapper()

# Create FarcasterToolkit from the api wrapper
farcaster_toolkit = FarcasterToolkit.from_farcaster_api_wrapper(farcaster_api_wrapper)
```

View available tools:
```python
tools = farcaster_toolkit.get_tools()
for tool in tools:
print(tool.name)
```

The toolkit provides the following tools:

1. **user_details** - Get user details by FID
2. **user_notifications** - Get notifications for the authenticated user
3. **cast** - Post a cast (max 320 characters, with optional channel and embeds)
4. **reply_to_cast** - Reply to an existing cast

### Using with an Agent

```python
import uuid

from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langgraph.prebuilt import create_react_agent

llm = ChatOpenAI(model="gpt-4o-mini")

# Create agent
agent_executor = create_react_agent(llm, tools)

# Example - post cast
events = agent_executor.stream(
{
"messages": [
HumanMessage(content=f"Please post 'Hello Farcaster! {uuid.uuid4().hex}' to Farcaster"),
],
},
stream_mode="values",
)

for event in events:
event["messages"][-1].pretty_print()
```

Expected output:
```
================================ Human Message =================================
Please post 'Hello Farcaster! c4b8e3744c2e4345be9e0622b4c0a8aa' to Farcaster
================================== Ai Message ==================================
Tool Calls:
cast (call_xVx4BMCSlCmCcbEQG1yyebbq)
Call ID: call_xVx4BMCSlCmCcbEQG1yyebbq
Args:
text: Hello Farcaster! c4b8e3744c2e4345be9e0622b4c0a8aa
================================= Tool Message =================================
Name: cast
Successfully posted!
================================== Ai Message ==================================
The message "Hello Farcaster! c4b8e3744c2e4345be9e0622b4c0a8aa" has been successfully posted to Farcaster!
```

### Advanced Usage

You can also specify a channel or include embeds when posting:

```python
# Post in a specific channel
response = farcaster_api_wrapper.cast(
text="Hello Python developers! 🐍",
channel_id="python"
)

# Post with an embedded URL
response = farcaster_api_wrapper.cast(
text="Check out this cool project!",
embeds=["https://github.com/example/project"]
)
```

## Contributing
See [CONTRIBUTING.md](../CONTRIBUTING.md) for detailed setup instructions and contribution guidelines.

## Documentation
For detailed documentation, please visit:
- [Agentkit-Core](https://coinbase.github.io/cdp-agentkit/cdp-agentkit-core/)
- [Neynar API Documentation](https://docs.neynar.com/)
20 changes: 20 additions & 0 deletions farcaster-langchain/docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
71 changes: 71 additions & 0 deletions farcaster-langchain/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Farcaster Langchain Toolkit
Farcaster integration with Langchain to enable agentic workflows using the core primitives defined in `cdp-agentkit-core`.

This toolkit contains tools that enable an LLM agent to interact with [Farcaster](https://www.farcaster.xyz/) via the [Neynar API](https://docs.neynar.com/). The toolkit provides a wrapper around the Neynar API, allowing agents to perform social operations like posting casts and replies.

## Setup

### Prerequisites
- Python 3.10 or higher
- [OpenAI API Key](https://platform.openai.com/api-keys)
- [Neynar API Key](https://docs.neynar.com/reference/getting-started)
- [Neynar Signer UUID](https://docs.neynar.com/reference/create-signer)
- Farcaster Account with FID

### Installation
bash
pip install farcaster-langchain

### Environment Setup

Set the following environment variables:
bash
export OPENAI_API_KEY=<your-openai-api-key>
export NEYNAR_API_KEY=<your-neynar-api-key>
export NEYNAR_SIGNER_UUID=<your-signer-uuid>
export FARCASTER_FID=<your-farcaster-id>

## API Reference

### FarcasterApiWrapper
The main wrapper class that handles interactions with the Farcaster API via Neynar.

#### Methods

##### cast
python
def cast(text: str, channel_id: Optional[str] = None, embeds: Optional[List[str]] = None) -> str

Post a new cast to Farcaster. Optionally specify a channel or include embedded URLs.

##### get_notifications
python
def get_notifications(fid: Optional[str] = None) -> str

Get recent notifications for the authenticated user or specified FID.

##### get_user_details

python
def get_user_details(username: str) -> str

Get details about a specific Farcaster user.

### FarcasterToolkit
A collection of LangChain tools for Farcaster interactions.

#### Available Tools
1. **user_details** - Get user details by FID
2. **user_notifications** - Get notifications for the authenticated user
3. **cast** - Post a cast (max 320 characters, with optional channel and embeds)
4. **reply_to_cast** - Reply to an existing cast

For detailed examples and usage, see the [main README](../README.md).

## Contributing
See [CONTRIBUTING.md](../CONTRIBUTING.md) for detailed setup instructions and contribution guidelines.

## Documentation
For detailed documentation, please visit:
- [Agentkit-Core](https://coinbase.github.io/cdp-agentkit/cdp-agentkit-core/)
- [Neynar API Documentation](https://docs.neynar.com/)
Loading