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.
102 lines
2.3 KiB
Go
102 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/hanzoai/agents/sdk/go/agent"
|
|
)
|
|
|
|
func main() {
|
|
nodeID := envOr("AGENT_NODE_ID", "go-serverless-func")
|
|
port := envOr("PORT", "8090")
|
|
|
|
cfg := agent.Config{
|
|
NodeID: nodeID,
|
|
Version: "1.0.0",
|
|
HanzoAgentsURL: strings.TrimSpace(os.Getenv("HANZO_AGENTS_URL")),
|
|
Token: os.Getenv("HANZO_AGENTS_TOKEN"),
|
|
ListenAddress: ":" + port,
|
|
DeploymentType: "serverless",
|
|
DisableLeaseLoop: true,
|
|
LeaseRefreshInterval: 0,
|
|
}
|
|
|
|
srv, err := agent.New(cfg)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
srv.RegisterReasoner("hello", func(ctx context.Context, input map[string]any) (any, error) {
|
|
exec := agent.ExecutionContextFrom(ctx)
|
|
name := strings.TrimSpace(defaultString(asString(input["name"]), "HanzoAgents"))
|
|
return map[string]any{
|
|
"greeting": "Hello, " + name + "!",
|
|
"run_id": exec.WorkflowID,
|
|
"execution_id": exec.ExecutionID,
|
|
"parent_execution_id": exec.ParentExecutionID,
|
|
}, nil
|
|
})
|
|
|
|
srv.RegisterReasoner("relay", func(ctx context.Context, input map[string]any) (any, error) {
|
|
target := strings.TrimSpace(defaultString(asString(input["target"]), os.Getenv("CHILD_TARGET")))
|
|
if target == "" {
|
|
return map[string]any{"error": "target is required"}, nil
|
|
}
|
|
message := defaultString(asString(input["message"]), "ping")
|
|
res, err := srv.Call(ctx, target, map[string]any{"name": message})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return map[string]any{
|
|
"target": target,
|
|
"downstream": res,
|
|
}, nil
|
|
})
|
|
|
|
addr := srvAddress(cfg.ListenAddress)
|
|
log.Printf("serverless handler listening on %s", addr)
|
|
if err := http.ListenAndServe(addr, srv.Handler()); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func envOr(name, fallback string) string {
|
|
value := strings.TrimSpace(os.Getenv(name))
|
|
if value == "" {
|
|
return fallback
|
|
}
|
|
return value
|
|
}
|
|
|
|
func srvAddress(listen string) string {
|
|
if strings.HasPrefix(listen, ":") {
|
|
return listen
|
|
}
|
|
if listen == "" {
|
|
return ":8090"
|
|
}
|
|
return listen
|
|
}
|
|
|
|
func defaultString(value, fallback string) string {
|
|
if strings.TrimSpace(value) == "" {
|
|
return fallback
|
|
}
|
|
return strings.TrimSpace(value)
|
|
}
|
|
|
|
func asString(value any) string {
|
|
switch v := value.(type) {
|
|
case string:
|
|
return v
|
|
case []byte:
|
|
return string(v)
|
|
default:
|
|
return ""
|
|
}
|
|
}
|