Typed persistent state for AI agents, in Go

Most agent frameworks are workflow engines. Forge is the state layer those engines operate on: typed, persistent, lifecycle-aware, and exposed via MCP. Here is why that distinction matters.

The Go ecosystem for AI agents is young. Google's Agent Development Kit for Go shipped in November 2025. The official MCP Go SDK followed. Both solve real problems: agent execution and tool connectivity. Neither addresses state.

That gap is where Forge sits.

Workflow engines vs state layers

Most agent frameworks are workflow engines. LangGraph defines state as a typed dictionary that flows through a graph of nodes. Temporal guarantees durable execution across long-running workflows. CrewAI coordinates role-based agent crews through task sequences. These are all correct solutions to the problem of "how do I make an agent do a sequence of things reliably."

They do not answer a different question: what does the agent operate *on*?

In most agentic systems, state lives in whatever database the application already uses, accessed through whatever API the agent can reach. The agent manages state transitions itself: it reads a record, decides the next action, writes the result back. State consistency is the agent's responsibility. Audit trail is the agent's responsibility. Access control is the agent's responsibility.

This works until it does not.

What Forge provides

Forge is a typed state layer. Content, or any typed structured data, is stored in Forge with explicit lifecycle states:

Draft → Scheduled → Published → Archived

These transitions are enforced by the framework, not by the agent. An agent that publishes a post does not decide what "published" means or what consequences follow. Forge handles the database write, fires the lifecycle signal, updates the sitemap, and delivers the MCP notification to subscribed clients. The agent calls publish_post. The state machine does the rest.

Access control is token-scoped. An agent with Author role can create and publish, but cannot delete. The boundary is enforced in the framework, not in a prompt.

Audit history is automatic. Every state transition is recorded: who did it, when, what the previous state was. No extra code.

The agent does not manage state. Forge manages state. The agent operates on it.

MCP as the interface

Forge exposes its state via MCP tools, generated automatically from every content type you define:

type Post struct {
    forge.Node
    Title string `forge:"required,min=3" forge_description:"The headline"`
    Body  string `forge:"required" forge_format:"markdown"`
}

This generates: create_post, update_post, publish_post, archive_post, list_posts, get_post. The schema includes field descriptions and format hints the agent reads at initialize time. No system prompt needed to explain what each field means.

Any MCP-compatible client can connect: Claude Desktop, Claude Code, a custom agent built on the official MCP Go SDK. Forge does not care which client is on the other side. The protocol is the interface.

forge-agent: the execution layer

forge-agent completes the picture. It is an embedded agent runtime that wires Forge's lifecycle signals directly to agent execution:

agentMod := flow.New(db, flow.Config{
    AnthropicKey: os.Getenv("ANTHROPIC_API_KEY"),
    MCPURL:       mcpURL,
    MCPToken:     mcpToken,
})
agentMod.Register(app)

Agent jobs are defined as AgentJob nodes, a Forge content type with the same lifecycle and MCP tools as any other type. A published job is active. An archived job is stopped. No redeploy required.

Two trigger types:

Signal-triggered: when AfterPublish fires for a Post, run this agent. The agent receives the full event context as JSON: type, slug, title, URL, previous state, actor role. It calls get_post, reads the body, and acts.

This is context engineering at the framework level. The agent receives exactly what it needs to act, structured by Forge, not assembled by the agent itself.

Cron-triggered: run this agent at 13:45 every day. Cron expression, IANA timezone. No external scheduler.

Both trigger types use the same agent loop: Anthropic API, tool use, MCP client, built-in HTTP tools. The agent reasons, calls tools, and writes results back to Forge via MCP, or to an external endpoint via HTTP POST.

What this looks like in practice

A post is published on forge-cms.dev. Forge fires AfterPublish. forge-agent picks up the signal and runs the devlog-social-drafts job. The agent calls get_post, reads the body, writes four social media drafts: two for X, two for Mastodon, and calls create_scheduled_post four times. The operator reviews the drafts and queues them. The posts go out on schedule.

Every step is a Forge state transition. Every draft has an audit trail. Every scheduled post went through the same lifecycle enforcement as any other content. The agent did not manage any of that. It called tools. Forge managed state.

Signal bus as coordination layer

When multiple agents operate on the same Forge application, the signal bus becomes a coordination mechanism without a central orchestrator. Agent 1 writes a specification and publishes it. Forge fires after_publish. Agent 2, subscribed via ContentTypeFilter, picks it up, without any direct connection between the two agents. The content lifecycle is the protocol.

This is different from graph-based frameworks where the workflow is defined upfront as an explicit DAG. In Forge, multi-agent coordination is emergent: you compose behaviours by publishing AgentJobs. The interactions follow from the state machine, and every step has an audit trail.

The Go angle

There is no mature Go agent framework with native MCP support and typed persistent state management. The Python ecosystem has LangGraph, CrewAI, AutoGen. Go has the MCP SDK and ADK, both released in late 2025, neither focused on state.

Forge does not compete with those frameworks. It gives Go applications a state layer that any agent, Python, Go, or otherwise, can operate on via MCP. The agent runtime (forge-agent) is embedded in your binary. No separate service. No Python dependency. One process.

For teams that want to own the agent layer: self-host, inspect, and control every part of the stack. This is the model.


forge v1.21.0, forge-agent v0.3.4.

*forge-agent on GitHub* *Signal bus: how lifecycle signals work* *MCP overview: how agents connect to Forge*