Observed since 20 Oct, 21:58 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
A plugin-based agent framework with CLI
Welcome to the official documentation for creating plugins for AgentForge. This guide will walk you through everything you need to know to build, test, and publish powerful tools on our marketplace.
By building a plugin, you're not just creating a tool; you're creating a new capability for thousands of AI agents, empowering users to automate their world in new and exciting ways.
The AgentForge SDK is a Python package that provides the CLI and base classes for development. Install it via pip:
pip install agentforge-sdk
Use the ag-cli tool to bootstrap a new plugin project:
ag-cli init my-weather-plugin
This command creates a new directory with a sample tool and your manifest file, agentforge.json.
The manifest is a JSON file that defines your plugin. It's the central configuration file that the AgentForge platform reads to understand your plugin's capabilities, dependencies, and metadata.
{
"manifestVersion": "1.0.0",
"name": "Weather Reporter",
"pluginId": "com.yourname.weather-reporter",
"version": "1.0.0",
"author": "Your Name <your.email@example.com>",
"description": "A plugin to get real-time weather information.",
"roleName": "Weather Specialist",
"personaPrompt": "You are a friendly weather assistant. You provide clear and concise weather updates.",
"tools": [ ... ],
"requirements": [ "requests" ],
"configurationSchema": [ ... ]
}
Key fields include pluginId, personaPrompt, and tools.
A tool is a single, executable function that an AI agent can call. Your tool code should reside in the tools/ directory. Every tool class must inherit from BaseTool and implement a run method.
from agentforge_sdk.base import BaseTool, ToolContext
class GetCurrentWeatherTool(BaseTool):
def run(self, **kwargs) -> str:
location = kwargs.get("location")
if not location:
return "Error: Please specify a location."
# Your API call logic here...
return f"The weather in {location} is sunny and 25°C."
If your tool needs sensitive information like an API key, define it in the configurationSchema section of your manifest. This creates a secure form for the user.
In your manifest:
"configurationSchema": [
{
"name": "weather_api_key",
"label": "Weather API Key",
"type": "secret",
"required": true,
"help_text": "Your API key from weatherapi.com"
}
]
Access this value in your tool's code via the ToolContext:
class GetCurrentWeatherTool(BaseTool):
def __init__(self, context: ToolContext):
super().__init__(context)
self.api_key = self.context.get_config("weather_api_key")
def run(self, **kwargs) -> str:
# Use self.api_key in your request
...
Your plugin can process files directly uploaded by users, such as text files, CSVs, or images. This is achieved using the special parameter type file_id.
file_id Parameter in Your Manifest"tools": [
{
"name": "analyze_csv",
"description": "Analyzes the data in a user-uploaded CSV file.",
"entrypoint": "tools.csv_analyzer:CSVAnalyzerTool",
"parameters": [
{
"name": "csv_file_ref",
"type": "file_id",
"description": "The reference ID of the CSV file to analyze.",
"required": true
}
]
}
]
When a user invokes your tool with a file, the AgentForge platform automatically resolves the file ID to a secure, temporary file path on the server. Your tool's run method will receive this path as a simple string.
import csv
class CSVAnalyzerTool(BaseTool):
def run(self, **kwargs) -> str:
# The argument name "csv_file_ref" matches the manifest
file_path = kwargs.get("csv_file_ref")
if not file_path:
return "Error: File reference was not provided."
try:
with open(file_path, 'r', encoding='utf-8') as f:
reader = csv.reader(f)
row_count = sum(1 for row in reader)
return f"Successfully analyzed the CSV file. It contains {row_count} rows."
except FileNotFoundError:
return "Error: The specified file could not be found on the server."
except Exception as e:
return f"An error occurred while processing the file: {str(e)}"
If your plugin generates new files (e.g., reports, processed CSVs, or images), you should save them using the get_artifacts_path method from the context. This ensures files are stored in the correct location and are accessible to the user.
Example:
class CSVAnalyzerTool(BaseTool):
def run(self, **kwargs) -> str:
output_path = self.context.get_artifacts_path("summary.txt")
output_path.write_text("Analysis complete: 120 rows processed.", encoding="utf-8")
return f"Report saved to {output_path}"
sales_report.csv.[File: sales_report.csv, ID: 123].analyze_csv(csv_file_ref="123")./tmp/path/to/sales_report.csv), and replaces the ID with the path.run method is finally executed with kwargs={'csv_file_ref': '/tmp/path/to/sales_report.csv'}.Before uploading, always validate your manifest to catch common errors:
cd my-weather-plugin
ag-cli validate
Once validation passes, package your plugin into an .afp file, ready for upload:
ag-cli package
pypistats · 58 observations shown. Missing days are unknown. Source category: overall: without mirrors.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-18 – 2026-10-18 | 7 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-17 – 2026-10-17 | 11 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-16 – 2026-10-16 | 2 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-15 – 2026-10-15 | 5 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-14 – 2026-10-14 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-13 – 2026-10-13 | 2 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-12 – 2026-10-12 | 6 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-11 – 2026-10-11 | 4 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-10 – 2026-10-10 | 8 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-09 – 2026-10-09 | 8 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-08 – 2026-10-08 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-06 – 2026-10-06 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-02 – 2026-10-02 | 2 | 2026-10-20T23:32:54.2349951Z |
| 2026-10-01 – 2026-10-01 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-30 – 2026-09-30 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-29 – 2026-09-29 | 2 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-28 – 2026-09-28 | 2 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-27 – 2026-09-27 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-26 – 2026-09-26 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-23 – 2026-09-23 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-22 – 2026-09-22 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-21 – 2026-09-21 | 2 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-20 – 2026-09-20 | 12 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-18 – 2026-09-18 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-17 – 2026-09-17 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-16 – 2026-09-16 | 2 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-14 – 2026-09-14 | 6 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-12 – 2026-09-12 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-10 – 2026-09-10 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-09 – 2026-09-09 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-07 – 2026-09-07 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-06 – 2026-09-06 | 3 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-05 – 2026-09-05 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-04 – 2026-09-04 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-09-01 – 2026-09-01 | 2 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-31 – 2026-08-31 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-28 – 2026-08-28 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-26 – 2026-08-26 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-24 – 2026-08-24 | 6 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-23 – 2026-08-23 | 3 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-22 – 2026-08-22 | 11 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-21 – 2026-08-21 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-18 – 2026-08-18 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-17 – 2026-08-17 | 3 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-14 – 2026-08-14 | 4 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-12 – 2026-08-12 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-11 – 2026-08-11 | 10 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-10 – 2026-08-10 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-09 – 2026-08-09 | 6 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-06 – 2026-08-06 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-05 – 2026-08-05 | 6 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-04 – 2026-08-04 | 3 | 2026-10-20T23:32:54.2349951Z |
| 2026-08-02 – 2026-08-02 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-07-29 – 2026-07-29 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-07-28 – 2026-07-28 | 2 | 2026-10-20T23:32:54.2349951Z |
| 2026-07-27 – 2026-07-27 | 14 | 2026-10-20T23:32:54.2349951Z |
| 2026-07-24 – 2026-07-24 | 1 | 2026-10-20T23:32:54.2349951Z |
| 2026-07-23 – 2026-07-23 | 6 | 2026-10-20T23:32:54.2349951Z |
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.4 | 20 Sept 2025 | 1 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 21:58 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:26cdb4b7e2384e793661d5613787e9ae372e07854fc6c0ac68709cdbc1122f77