Files
openfang/sdk/python/openfang_sdk.py
jaberjaber23 5692c96494 Initial commit — OpenFang Agent Operating System
Open-source Agent OS built in Rust.

- 14 crates, 1,767+ tests, zero clippy warnings
- 7 autonomous Hands (Clip, Lead, Collector, Predictor, Researcher, Twitter, Browser)
- 16 security systems (WASM sandbox, Merkle audit trail, taint tracking, Ed25519 signing, SSRF protection, secret zeroization, HMAC-SHA256 mutual auth, and more)
- 30 pre-built agents across 4 performance tiers
- 40 channel adapters (Telegram, Discord, Slack, WhatsApp, Teams, and 35 more)
- 38 built-in tools + MCP client/server + A2A protocol
- 26 LLM providers with intelligent routing and cost tracking
- 60+ bundled skills with FangHub marketplace
- Tauri 2.0 native desktop app
- 140+ REST/WS/SSE API endpoints with Alpine.js dashboard
- OpenAI-compatible /v1/chat/completions endpoint
- One-command install, production-ready
2026-02-26 01:00:27 +03:00

148 lines
4.0 KiB
Python

"""
OpenFang Python SDK — helper library for writing Python agents.
Usage:
from openfang_sdk import Agent
agent = Agent()
@agent.on_message
def handle(message: str, context: dict) -> str:
return f"You said: {message}"
agent.run()
Or for simple scripts without the decorator pattern:
from openfang_sdk import read_input, respond
data = read_input()
result = f"Echo: {data['message']}"
respond(result)
"""
import json
import os
import sys
from typing import Callable, Optional, Dict, Any
def read_input() -> Dict[str, Any]:
"""Read the input JSON from stdin (sent by the OpenFang kernel)."""
line = sys.stdin.readline().strip()
if not line:
# Fallback: check environment variables
agent_id = os.environ.get("OPENFANG_AGENT_ID", "")
message = os.environ.get("OPENFANG_MESSAGE", "")
return {
"type": "message",
"agent_id": agent_id,
"message": message,
"context": {},
}
return json.loads(line)
def respond(text: str, metadata: Optional[Dict[str, Any]] = None) -> None:
"""Send a response back to the OpenFang kernel via stdout."""
response = {"type": "response", "text": text}
if metadata:
response["metadata"] = metadata
print(json.dumps(response), flush=True)
def log(message: str, level: str = "info") -> None:
"""Log a message to stderr (visible in OpenFang daemon logs)."""
print(f"[{level.upper()}] {message}", file=sys.stderr, flush=True)
class Agent:
"""Decorator-based Python agent framework.
Example:
agent = Agent()
@agent.on_message
def handle(message: str, context: dict) -> str:
return f"Hello! You said: {message}"
agent.run()
"""
def __init__(self):
self._handler: Optional[Callable] = None
self._setup: Optional[Callable] = None
self._teardown: Optional[Callable] = None
def on_message(self, func: Callable) -> Callable:
"""Register a message handler function.
The function should accept (message: str, context: dict) and return str.
"""
self._handler = func
return func
def on_setup(self, func: Callable) -> Callable:
"""Register a setup function called once before message handling."""
self._setup = func
return func
def on_teardown(self, func: Callable) -> Callable:
"""Register a teardown function called once after message handling."""
self._teardown = func
return func
def run(self) -> None:
"""Run the agent, reading input and producing output."""
if self._handler is None:
log("No message handler registered", "error")
sys.exit(1)
try:
if self._setup:
self._setup()
data = read_input()
message = data.get("message", "")
context = data.get("context", {})
result = self._handler(message, context)
if isinstance(result, str):
respond(result)
elif isinstance(result, dict):
respond(result.get("text", str(result)), result.get("metadata"))
else:
respond(str(result))
except Exception as e:
log(f"Agent error: {e}", "error")
respond(f"Error: {e}")
sys.exit(1)
finally:
if self._teardown:
try:
self._teardown()
except Exception as e:
log(f"Teardown error: {e}", "error")
# Convenience: if this file is run directly, show usage
if __name__ == "__main__":
print("OpenFang Python SDK")
print("====================")
print()
print("Import this module in your agent scripts:")
print()
print(" from openfang_sdk import Agent")
print()
print(" agent = Agent()")
print()
print(" @agent.on_message")
print(" def handle(message, context):")
print(" return f'You said: {message}'")
print()
print(" agent.run()")