MAS is a lightweight, pluggable Go multi‑agent SDK focused on simplicity and composability.
- Lightweight: an Agent is just a description (prompt + tools)
- Pluggable: the Runner owns the execution loop and can be customized
- Easy to start: 3–5 lines to run a single agent
go get github.com/voocel/maspackage main
import (
"context"
"fmt"
"os"
"github.com/voocel/mas"
"github.com/voocel/mas/agent"
"github.com/voocel/mas/llm"
"github.com/voocel/mas/runner"
"github.com/voocel/mas/schema"
"github.com/voocel/mas/tools/builtin"
)
func main() {
model := llm.NewOpenAIModel(
"gpt-5",
os.Getenv("OPENAI_API_KEY"),
os.Getenv("OPENAI_API_BASE_URL"),
)
// Minimal entry (recommended)
resp, err := mas.Query(
context.Background(),
model,
"Compute 15 * 8 + 7",
mas.WithPreset("assistant"),
mas.WithTools(builtin.NewCalculator()),
)
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(resp.Content)
// Advanced: custom Runner
ag := agent.New(
"assistant",
"assistant",
agent.WithSystemPrompt("You are a helpful assistant."),
agent.WithTools(builtin.NewCalculator()),
)
r := runner.New(runner.Config{Model: model})
resp, err := r.Run(context.Background(), ag, schema.Message{
Role: schema.RoleUser,
Content: "Compute 15 * 8 + 7",
})
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(resp.Content)
}cli, _ := mas.NewClient(
model,
mas.WithPreset("assistant"),
mas.WithTools(builtin.NewCalculator()),
)
resp, _ := cli.Send(context.Background(), "Continue with 9 * 9")format := &llm.ResponseFormat{
Type: "json_object",
}
resp, _ := mas.Query(
context.Background(),
model,
"Return JSON {\"answer\": 42}",
mas.WithResponseFormat(format),
)result, _ := mas.QueryWithResult(
context.Background(),
model,
"Compute 6 * 7",
)
fmt.Println(result.Message.Content, result.Usage.TotalTokens)import "github.com/voocel/mas/multi"
team := multi.NewTeam()
team.Add("researcher", researcher)
team.Add("writer", writer)
ag, _ := team.Route("researcher")
resp, _ := runner.Run(ctx, ag, msg)// Sequential collaboration
resp, _ := multi.RunSequential(ctx, r, []*agent.Agent{researcher, writer}, msg)
// Parallel collaboration + reduce
resp, _ := multi.RunParallel(ctx, r, []*agent.Agent{a1, a2}, msg, multi.FirstReducer)
// Dynamic routing (handoff)
router := &multi.KeywordRouter{
Rules: map[string]string{"stats": "analyst", "write": "writer"},
Default: "assistant",
}
resp, _ := multi.RunHandoff(ctx, r, team, router, msg, multi.WithMaxSteps(3))import "github.com/voocel/mas/middleware"
r := runner.New(runner.Config{
Model: model,
Middlewares: []runner.Middleware{
&middleware.TimeoutMiddleware{LLMTimeout: 10 * time.Second, ToolTimeout: 20 * time.Second},
&middleware.RetryMiddleware{MaxAttempts: 3},
middleware.NewToolAllowlist("calculator", "web_search"),
middleware.NewToolCapabilityPolicy(
middleware.AllowOnly(tools.CapabilityNetwork),
middleware.Deny(tools.CapabilityFile),
),
},
})import "github.com/voocel/mas/observer"
r := runner.New(runner.Config{
Model: model,
Observer: observer.NewLoggerObserver(os.Stdout),
Tracer: observer.NewSimpleTimerTracer(os.Stdout),
})Logs include run_id, step_id, and span_id for correlation.
import (
"github.com/voocel/mas/middleware"
"github.com/voocel/mas/observer"
)
metrics := &middleware.MetricsObserver{}
obs := observer.NewCompositeObserver(
observer.NewJSONObserver(os.Stdout),
metrics,
)router := &multi.KeywordRouter{
Rules: map[string]string{"stats": "analyst", "write": "writer"},
Default: "assistant",
}
ag, _ := router.Select(msg, team)- Agent: describes role, system prompt and tools
- Runner: drives the execution loop (LLM → tools → feedback)
- Tool: independent capability with optional side‑effect flags
- Memory: conversation store (in‑memory window by default)
Apache License 2.0