mirror of
https://github.com/hanzoai/agents.git
synced 2026-10-30 18:48:36 +00:00
Transforms hanzoai/agents from a marketplace config repo into a full agent orchestration platform by merging the AgentField infrastructure: - Go control plane (K8s-like agent orchestration, service mesh, DAG workflows) - Python SDK (FastAPI-based agent framework, LiteLLM, memory, DID/VC) - TypeScript SDK (@hanzo/agents - Vercel AI SDK, MCP, workflows) - Go SDK (idiomatic agent builder + client) - React 19 embedded dashboard (XyFlow DAGs, Recharts, Radix UI) - Docker/K8s/Helm deployment configs - Examples: hello world, deep research, RAG, simulation, benchmarks - Functional test suite across Python/Go/TypeScript All references rebranded: AgentField → Hanzo Agents - Module: github.com/hanzoai/agents/control-plane - Python: hanzo_agents - TypeScript: @hanzo/agents - Go: github.com/hanzoai/agents/sdk/go - Env vars: HANZO_AGENTS_* - Config: hanzo-agents.yaml Previous marketplace configs moved to config/ directory.
96 lines
2.7 KiB
Go
96 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/hanzoai/agents/sdk/go/agent"
|
|
)
|
|
|
|
func main() {
|
|
nodeID := strings.TrimSpace(os.Getenv("AGENT_NODE_ID"))
|
|
if nodeID == "" {
|
|
nodeID = "go-serverless-hello"
|
|
}
|
|
|
|
cfg := agent.Config{
|
|
NodeID: nodeID,
|
|
Version: "1.0.0",
|
|
HanzoAgentsURL: strings.TrimSpace(os.Getenv("HANZO_AGENTS_URL")),
|
|
Token: os.Getenv("HANZO_AGENTS_TOKEN"),
|
|
DeploymentType: "serverless",
|
|
ListenAddress: ":" + defaultString(os.Getenv("PORT"), "8085"),
|
|
LeaseRefreshInterval: 0, // no lease loop in serverless mode
|
|
DisableLeaseLoop: true,
|
|
}
|
|
|
|
srv, err := agent.New(cfg)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
srv.RegisterReasoner("hello", func(ctx context.Context, input map[string]any) (any, error) {
|
|
name := strings.TrimSpace(defaultString(toString(input["name"]), "HanzoAgents"))
|
|
return map[string]any{
|
|
"greeting": "Hello, " + name + "!",
|
|
"name": name,
|
|
}, nil
|
|
})
|
|
|
|
srv.RegisterReasoner("relay", func(ctx context.Context, input map[string]any) (any, error) {
|
|
target := strings.TrimSpace(defaultString(toString(input["target"]), os.Getenv("CHILD_TARGET")))
|
|
if target == "" {
|
|
return map[string]any{"error": "target is required"}, nil
|
|
}
|
|
message := strings.TrimSpace(defaultString(toString(input["message"]), "ping"))
|
|
|
|
res, err := srv.Call(ctx, target, map[string]any{"message": message})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return map[string]any{
|
|
"target": target,
|
|
"downstream": res,
|
|
}, nil
|
|
})
|
|
|
|
// Optional local server for manual testing
|
|
addr := cfg.ListenAddress
|
|
log.Printf("serverless handler listening on %s", addr)
|
|
if err := http.ListenAndServe(addr, srv.Handler()); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// For platforms that invoke a function instead of an HTTP listener, you can adapt
|
|
// the event and delegate to the agent:
|
|
//
|
|
// func LambdaHandler(ctx context.Context, event map[string]any) (map[string]any, error) {
|
|
// result, status, err := srv.HandleServerlessEvent(ctx, event, nil) // adapter optional
|
|
// if err != nil {
|
|
// return map[string]any{"statusCode": 500, "body": map[string]any{"error": err.Error()}}, nil
|
|
// }
|
|
// return map[string]any{"statusCode": status, "body": result}, nil
|
|
// }
|
|
}
|
|
|
|
func defaultString(value, fallback string) string {
|
|
if strings.TrimSpace(value) == "" {
|
|
return fallback
|
|
}
|
|
return strings.TrimSpace(value)
|
|
}
|
|
|
|
func toString(value any) string {
|
|
if value == nil {
|
|
return ""
|
|
}
|
|
if s, ok := value.(string); ok {
|
|
return s
|
|
}
|
|
return strings.TrimSpace(strings.ReplaceAll(strings.TrimSpace(strings.Trim(fmt.Sprintf("%v", value), "\n")), "\t", " "))
|
|
}
|