Files
zeekayandGitHub 5b5cf9e9db feat: merge AgentField control plane + SDKs as Hanzo Agents (#1)
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.
2026-02-09 18:53:09 -08:00

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", " "))
}