-
Notifications
You must be signed in to change notification settings - Fork 8
Add AG2 integration #27
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| # TinyFish Web Agent — AG2 Integration | ||
|
|
||
| [TinyFish](https://tinyfish.ai) Search and Fetch are available to [AG2](https://github.com/ag2ai/ag2) agents through | ||
| `TinyFishSearchToolkit`, shipped **inside AG2 itself** — there is no separate adapter package to install. | ||
|
|
||
| Requires **AG2 >= 1.0.0**. | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| pip install "ag2[anthropic]>=1.0.0" "tinyfish>=0.5,<0.6" | ||
| ``` | ||
|
|
||
| The toolkit lives in `ag2.extensions.tools.search`. AG2 extensions are not shipped as extras, so the | ||
| `tinyfish` SDK is installed directly alongside AG2. Python 3.11+ is required (a constraint of the | ||
| `tinyfish` SDK). | ||
|
|
||
| The `[anthropic]` extra installs the model provider used in the examples below. Swap it for whichever | ||
| provider you run — `ag2[openai]`, `ag2[gemini]`, `ag2[bedrock]`, `ag2[mistral]`, `ag2[ollama]`, | ||
| `ag2[xai]` — or combine them: `ag2[anthropic,openai]`. The TinyFish tools themselves are | ||
| provider-agnostic. | ||
|
|
||
| ## Setup | ||
|
|
||
| Get your API key at [agent.tinyfish.ai/api-keys](https://agent.tinyfish.ai/api-keys): | ||
|
|
||
| ```bash | ||
| export TINYFISH_API_KEY="your-api-key" | ||
| export ANTHROPIC_API_KEY="your-anthropic-key" # or any other AG2-supported provider | ||
| ``` | ||
|
|
||
| AG2 sets `TF_API_INTEGRATION=ag2` around every TinyFish SDK call, so requests are attributed to AG2 | ||
| automatically. Any value you set yourself is restored after the call, so an outer `TF_API_INTEGRATION` | ||
| is never clobbered. | ||
|
|
||
| ## Tools | ||
|
|
||
| | Tool | Description | | ||
| |------|-------------| | ||
| | `tinyfish_search` | Search the web. Returns ranked results with titles, snippets, site names, and URLs. | | ||
| | `tinyfish_fetch` | Fetch browser-rendered content for 1–10 URLs. Returns extracted content plus per-URL errors. | | ||
|
|
||
| ## Usage | ||
|
|
||
| ### Basic agent | ||
|
|
||
| Passing the toolkit registers both tools: | ||
|
|
||
| ```python | ||
| import os | ||
|
|
||
| from ag2 import Agent | ||
| from ag2.config import AnthropicConfig | ||
| from ag2.extensions.tools.search import TinyFishSearchToolkit | ||
|
|
||
| agent = Agent( | ||
| "researcher", | ||
| config=AnthropicConfig(model="claude-sonnet-4-6"), | ||
| tools=[TinyFishSearchToolkit(api_key=os.environ["TINYFISH_API_KEY"])], | ||
| ) | ||
|
|
||
| await agent.ask("Find the current pricing tiers on tinyfish.ai and summarise them.") | ||
| ``` | ||
|
|
||
| If `api_key` is omitted, the TinyFish SDK reads `TINYFISH_API_KEY` from the environment. | ||
|
|
||
| ### Picking a subset of tools | ||
|
|
||
| Each tool is exposed as a factory method on the toolkit. Call the method to get a ready-to-use tool | ||
| and pass only the ones you need: | ||
|
|
||
| ```python | ||
| toolkit = TinyFishSearchToolkit() | ||
|
|
||
| agent = Agent( | ||
| "reader", | ||
| config=AnthropicConfig(model="claude-sonnet-4-6"), | ||
| tools=[toolkit.fetch()], | ||
| ) | ||
| ``` | ||
|
Comment on lines
+72
to
+80
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- README references ---'
rg -n -C 5 'config|AnthropicConfig|TinyFishSearchToolkit|await|Agent\(' ag2/README.md
printf '%s\n' '--- README lines 1-130 ---'
sed -n '1,130p' ag2/README.md
printf '%s\n' '--- Standalone Python behavior probe ---'
python3 - <<'PY'
source = '''
from anthropic import AnthropicConfig
from ag2 import Agent
agent = Agent(
"reader",
config=config,
)
'''
try:
compile(source, "<README snippet>", "exec")
print("compile: success")
except Exception as exc:
print(f"compile: {type(exc).__name__}: {exc}")
namespace = {}
try:
exec(compile(source, "<README snippet>", "exec"), namespace)
except Exception as exc:
print(f"execution: {type(exc).__name__}: {exc}")
PYRepository: tinyfish-io/tinyfish-web-agent-integrations Length of output: 6340 🏁 Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
source = '''
toolkit = TinyFishSearchToolkit()
search_tool = toolkit.search(
location="US",
language="en",
)
fetch_tool = toolkit.fetch(
format="markdown",
links=True,
image_links=False,
)
agent = Agent("researcher", config=config, tools=[search_tool, fetch_tool])
'''
class Toolkit:
def search(self, **kwargs):
return ("search", kwargs)
def fetch(self, **kwargs):
return ("fetch", kwargs)
def Agent(*args, **kwargs):
return {"args": args, "kwargs": kwargs}
namespace = {
"TinyFishSearchToolkit": Toolkit,
"Agent": Agent,
}
try:
exec(compile(source, "<README per-tool example>", "exec"), namespace)
except Exception as exc:
print(f"execution: {type(exc).__name__}: {exc}")
else:
print("execution: success")
PYRepository: tinyfish-io/tinyfish-web-agent-integrations Length of output: 232 Define Line 100 uses 🤖 Prompt for AI Agents |
||
|
|
||
| ### Per-tool configuration | ||
|
|
||
| Per-call parameters live on the factory methods: | ||
|
|
||
| ```python | ||
| toolkit = TinyFishSearchToolkit() | ||
|
|
||
| search_tool = toolkit.search( | ||
| location="US", # search locale | ||
| language="en", | ||
| ) | ||
|
|
||
| fetch_tool = toolkit.fetch( | ||
| format="markdown", # "markdown" | "html" | "json" | ||
| links=True, # include hyperlinks in the extracted content | ||
| image_links=False, | ||
| ) | ||
|
|
||
| agent = Agent("researcher", config=config, tools=[search_tool, fetch_tool]) | ||
| ``` | ||
|
|
||
| Defaults can also be fixed once on the constructor and are applied to both default tools: | ||
|
|
||
| ```python | ||
| toolkit = TinyFishSearchToolkit( | ||
| location="US", | ||
| language="en", | ||
| format="markdown", | ||
| links=True, | ||
| base_url=None, # override the API endpoint | ||
| timeout=60.0, | ||
| max_retries=3, | ||
| ) | ||
| ``` | ||
|
|
||
| ### Runtime values with `Variable` | ||
|
|
||
| Every runtime parameter accepts an AG2 `Variable`, resolved from the run context at execution time | ||
| instead of being fixed when the tool is built: | ||
|
|
||
| ```python | ||
| from ag2.annotations import Variable | ||
|
|
||
| toolkit = TinyFishSearchToolkit() | ||
| search_tool = toolkit.search(location=Variable("user_country")) | ||
| ``` | ||
|
|
||
| ## Notes | ||
|
|
||
| - `tinyfish_fetch` accepts 1–10 URLs per call and rejects any URL that is not `http`/`https`. | ||
| - Both tools are async and run natively on AG2's async execution path. | ||
|
|
||
| ## Support | ||
|
|
||
| - [TinyFish Docs](https://docs.tinyfish.ai) | ||
| - [AG2 TinyFish tool docs](https://docs.ag2.ai/docs/user-guide/extensions/tools/search/tinyfish/) | ||
| - [AG2 repository](https://github.com/ag2ai/ag2) | ||
| - [Discord](https://discord.com/invite/tinyfish) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: tinyfish-io/tinyfish-web-agent-integrations
Length of output: 244
🏁 Script executed:
Repository: tinyfish-io/tinyfish-web-agent-integrations
Length of output: 4206
🌐 Web query:
AG2 1.0 Agent.ask AgentReply reply.body documentation💡 Result:
In the AG2 (formerly AutoGen) framework, the Agent.ask method and the AgentReply object are core components for managing agent interactions [1][2]. Agent.ask The Agent.ask(...) method is used to initiate a new conversation turn [1][3]. It is a blocking operation that runs until the turn completes, at which point it returns an AgentReply object [1][4][5]. It is designed for scenarios where you simply want to retrieve an agent's response to a given input [1][3]. AgentReply and reply.body An AgentReply object represents the result of a completed turn [1][6]. It contains metadata and the model's response for that specific turn [7][8]. - reply.body: This property provides the raw text output generated by the model for that turn [1][6][5]. - Context Preservation: Calling.ask(...) on an existing AgentReply object continues the conversation, allowing the agent to maintain context and history from previous turns [1][5][9]. Structured Output For structured responses, you can use the reply.content method (awaitable) instead of reply.body, which returns the output parsed according to the defined response_schema [6]. If no schema is specified or if you only need the raw text, reply.body is the appropriate property [6].
Citations:
🏁 Script executed:
Repository: tinyfish-io/tinyfish-web-agent-integrations
Length of output: 581
🏁 Script executed:
Repository: tinyfish-io/tinyfish-web-agent-integrations
Length of output: 581
🏁 Script executed:
Repository: tinyfish-io/tinyfish-web-agent-integrations
Length of output: 5222
Make the basic example runnable and show its result.
When users copy this block into a normal
.pyfile, line 62 fails becauseawaitis outside a function. Wrap the call inasync def main(), printreply.body, and invokeasyncio.run(main()).🤖 Prompt for AI Agents