Agentic networks
An agent that can reach anything is an agent you cannot reason about. AgentArea borrows the mental model network engineers already have — the virtual private cloud — and applies it to agents: a workspace is a private network, the agents and tools inside it are hosts, and the interesting question is always which of them can reach the outside world. The analogy is a way to see your system. Read this page for what it buys you and, equally, for where it stops being enforcement and becomes a picture.The problem
A workspace accumulates agents, skills, MCP server instances and triggers. After a few dozen entities, two questions get hard to answer at a glance:- Which of these can talk to the internet? An MCP server instance that calls the GitHub API is a very different risk from one that reads a local file.
- Where does data leave the governed environment? Untrusted model output plus an unnoticed outbound connection is the shape of most agent data-exfiltration incidents.
How AgentArea approaches it
Three ideas, in decreasing order of how strongly they are enforced.The workspace is the isolation boundary
This one is real enforcement, in the database, on every query. Every entity inheritsWorkspaceScopedMixin and every repository extends
WorkspaceScopedRepository, whose _get_workspace_filter() constrains reads to
the caller’s accessible_workspaces. A row belonging to another workspace is not
filtered out of the UI — it is never selected.
UserContext (user_id, workspace_id, accessible_workspaces) is required to
construct any repository, via RepositoryFactory. There is no ambient
“current workspace” to forget to pass, which is what makes the boundary hold.
Relationships decide access inside the boundary
Within a workspace, authorization is relationship-based (ReBAC), evaluated by OpenFGA or Ory Keto. The deployed model defines these types:
Access flows down: a
resource inherits from its project, a project from its
parent and its workspace. This is the part of the network model that actually
gates requests.
Zone labels describe external reach
Skills and MCP server instances carry anetwork_scope field with three values:
The network view renders these as three zones left to right — gateway, governed
internal, egress — and highlights edges that cross from internal to egress, so an
ungoverned outbound path is visible without running an audit.
Read the next section before you rely on that field for anything.
What is enforced and what is presented
This distinction matters more than the analogy, so it gets its own table.
The
network_scope field was introduced as the foundation for later policy
enforcement, and that later has not arrived. Setting a skill to private today
documents an intention; it does not confine anything. Treat the zone view as an
inventory that makes risk legible, not as a control that removes it.
Actual egress restriction, where it exists, comes from the sandbox data plane
rather than from network_scope. The operator selects one deployment-level
internet policy; task callers cannot choose or weaken it. The built-in
Kubernetes provider renders that choice as NetworkPolicy, while external
providers must enforce the equivalent contract themselves. It remains unaware
of the label on the skill.
Why not enforce network_scope directly?
The obvious move is to makenetwork_scope binding: refuse to start an MCP
server instance marked private if it opens a socket. Two things make that
harder than it sounds.
The label is a declaration, not an observation. network_scope defaults to
private and is set by whoever registers the skill or instance. Enforcing an
unverified self-declaration gives you the appearance of a control while an
incorrect label silently grants an exemption. Enforcement has to derive from
something the platform observes — the pod’s actual network policy — rather than
from a field a user typed.
The enforcement point is in a different plane. Traffic leaves from a sandbox
pod or an MCP container in the data plane. The label lives on a control-plane
row. Making the label binding means propagating it into pod-level network policy
on every backend the manager supports, and failing closed when a backend cannot
express it. That is a real project, not a validation rule.
So the honest position is the current one: the model is enforced at the workspace
and relation layer, where the platform genuinely mediates every access, and the
zone layer is descriptive until the pod-level plumbing exists to back it. Naming
that gap is better than letting you infer a containment guarantee that is not
there.
Why not a generic agent graph?
The first version of the network view was a flat React Flow graph: every entity a node, every relationship an identical edge. It was abandoned because it answered neither operator question. A graph that shows you forty nodes and eighty edges communicates that your system is complicated, which you knew. Zones beat a force-directed layout here because the reader arrives with a specific question — what touches the outside? — and zone membership answers it positionally, before any edge is traced. The cost is that the layout is static rather than draggable, and it gets crowded at high entity counts.Limits
network_scopeis not a security control. It does not block, filter, or restrict any connection. Do not use it as a compensating control in a threat model or a compliance narrative.- There is no inter-agent communication policy. Any agent in a workspace can
address any other agent in that workspace it has a relation to. Documentation
elsewhere that shows a
network_policyYAML block or anA2ABridgethat raisesCommunicationDeniedErrordescribes something that was never built. - Cross-workspace isolation depends on
accessible_workspacesbeing correct. It is resolved during authentication. A token minted with a broader workspace list than intended widens the boundary, and no lower layer will catch it. - Zone classification for triggers is automatic and coarse. Webhook triggers are ingress; everything else is private. A trigger that reaches out on a schedule is still labelled private.
- The label does not survive into the data plane. Nothing in the Go MCP
manager or the sandbox runtime reads
network_scope.
Related
- Workspaces, projects, and resources — the scoping model this network sits on
- Control plane and data plane — why the enforcement point and the label live in different places
- The AgentArea authorization model — the relations that are enforced
- Why a sandbox — where egress restriction actually happens