待翻譯:Subs, the cloud native agent harness
AI 服務暫時不可用,以下為來源摘要,待恢復後補全翻譯:Run a local agent. Create a subs.toml. subs.toml name = "example" [llm.openrouter] type = "openrouter" [agent.teammate] llm = "openrouter" model = "deepseek/deepseek-v4-flash-0731" system = "You are a helpful teammate."…
AI 服務暫時不可用,以下為來源正文,待恢復後補全翻譯。
Run a local agent. Create a subs.toml. subs.toml name = "example" [llm.openrouter] type = "openrouter" [agent.teammate] llm = "openrouter" model = "deepseek/deepseek-v4-flash-0731" system = "You are a helpful teammate." Talk to it. Use server/client mode. Add this to subs.toml. subs.toml name = "example"[llm.openrouter]type = "openrouter"[agent.teammate]llm = "openrouter"model = "deepseek/deepseek-v4-flash-0731"system = "You are a helpful teammate."[serve]port = 9999auth = false[remote]url = "http://localhost:9999" Start the server. In another terminal, the same command now talks to it. Run it on substructure.ai Point the same file at the hosted engine instead of your own. subs.toml name = "example"[llm.openrouter]type = "openrouter"[agent.teammate]llm = "openrouter"model = "deepseek/deepseek-v4-flash-0731"system = "You are a helpful teammate."[remote]url = "https://api.substructure.ai" Create the project from the file, then give it your LLM key. The same command as before. The turn runs on our machines now. Put the agent in Slack. Three lines: which agent takes a DM, and which answers a mention. subs.toml name = "example"[llm.openrouter]type = "openrouter"[agent.teammate]llm = "openrouter"model = "deepseek/deepseek-v4-flash-0731"system = "You are a helpful teammate."[agent.teammate.slack]name = "Teammate"[remote]url = "https://api.substructure.ai" Apply it again, then set up its Slack app. Mention the bot in a channel and it answers in the thread. You wrote one file and no code. Connect the agent to an MCP server Add the server. Give it to an agent. The credential is shared amongst all your users. subs.toml name = "example"[llm.openrouter]type = "openrouter"[mcp.sentry]url = "https://mcp.sentry.dev/mcp"[agent.teammate]llm = "openrouter"model = "deepseek/deepseek-v4-flash-0731"system = "You are a helpful teammate."mcp = ["mcp.sentry"][agent.teammate.slack]name = "Teammate"[remote]url = "https://api.substructure.ai" Authorize the MCP. Scope MCP connections to each user Mark a connection per-user. Each user connects their own account. User scoped MCP connections restricted to one-on-one agent and user chat contexts. subs.toml name = "example"[llm.openrouter]type = "openrouter"[mcp.sentry]url = "https://mcp.sentry.dev/mcp"[mcp.linear]url = "https://mcp.linear.app/mcp"credential = "user"[agent.teammate]llm = "openrouter"model = "deepseek/deepseek-v4-flash-0731"system = "You are a helpful teammate."mcp = ["mcp.sentry"][agent.teammate.slack]name = "Teammate"[agent.personal]llm = "openrouter"model = "deepseek/deepseek-v4-flash-0731"system = "Help me with my Linear issues."mcp = ["mcp.linear"][agent.personal.slack]name = "Personal"answers = "dm"[remote]url = "https://api.substructure.ai" Control the agent loop with webhooks. Configure the engine to send a webhook to your system and take complete control over the agent loop and Slack agent behavior. Point an agent at a URL that implements the substructure webhook. subs.toml name = "example"[llm.openrouter]type = "openrouter"[mcp.sentry]url = "https://mcp.sentry.dev/mcp"[mcp.linear]url = "https://mcp.linear.app/mcp"credential = "user"[agent.teammate]llm = "openrouter"model = "deepseek/deepseek-v4-flash-0731"system = "You are a helpful teammate."mcp = ["mcp.sentry"]worker = "https://example.com/agent"[agent.teammate.slack]name = "Teammate"[agent.personal]llm = "openrouter"model = "deepseek/deepseek-v4-flash-0731"system = "Help me with my Linear issues."mcp = ["mcp.linear"][agent.personal.slack]name = "Personal"answers = "dm" You handle a webhook, customizing just the steps you care about. You don't even need an SDK. server.ts import { serve } from "@hono/node-server"; import { Hono } from "hono"; import type { DecisionRequest, DecisionResponse } from "./protocol.ts"; function decide({ trigger, proposed }: DecisionRequest): DecisionResponse { if (trigger.type === "session.start") { return { agent: { ...proposed.agent, tools: [{ name: "current_time", description: "Get the current time" }] } }; } // Run our tool when the model calls it. if (trigger.type === "tool.execute" && trigger.name === "current_time") { return { actions: [{ type: "tool.result", result: new Date().toISOString() }] }; } // Accept the engine's proposal for everything else. return proposed; } const app = new Hono(); app.post("/", async (c) => c.json(decide(await c.req.json()))); serve({ fetch: app.fetch, port: 4444 }); Bring your own LLM. Bring your own key and the engine makes requests on your behalf. If you don't want to put your key in the engine, you can make calls in a webhook worker. Anthropic OpenAI OpenRouter Everything else your agents can do. Slack Mention the bot or DM it. The thread is the session. Route different channels to different agents. Workers At each step the engine tells your code what it plans to do next. Accept the plan or do something else. Any LLM The engine calls Anthropic, OpenAI, or OpenRouter with your key. Or your worker makes the call and the engine never sees a key. CLI Set up, deploy, watch, and debug from the terminal. It also runs the engine locally. MCP connectors Declare an MCP server and the engine handles the authorization, reads the tools it offers, and runs every call. Your code never holds a token. Plugins Point an agent at an agent-plugins directory and it gets that plugin's skills and MCP servers. AG-UI The engine streams AG-UI events, so assistant-ui and CopilotKit connect to it directly. Any language Your agent is an HTTP endpoint. Generate typed bindings from the published JSON schema. Subagents An agent gives work to other agents. Each child runs in its own session, and the parent's totals include its cost. Human approval An agent can stop and wait for a person, then continue. A waiting agent uses no compute. In Slack it is a button. Tool calls Give a tool an input and output schema. The engine checks every call against it. Tools that take hours A tool does not have to answer immediately. Accept the call, do the work on your own schedule, report the result later. Durability Every step is saved before it runs. A deploy, a crash, or a reconnect loses nothing. Conversations History, editing, regeneration, and branching belong to the engine. Edit an earlier message and go a new direction; the original branch stays. Host it yourself Run the engine on your own servers and hold every credential.