Shared Places – How Two Agentic-Nets Talk Through a Single Token Pool
What if two completely separate workflow nets could communicate without APIs, message queues, or event buses? Just by pointing at the same place? This is the story of shared places in AgenticOS — a pattern where multiple Agentic-Nets read from and write to the same runtime token pool, enabling cross-net communication with zero integration code. We built it, tested it with a live Claude Code pipeline, and now it’s a first-class feature with discovery tooling.
The Problem: Nets That Can’t See Each Other
AgenticOS models complex operations as Agentic-Nets — Petri nets where places hold tokens, transitions process them, and arcs define the flow. One net per concern: a scanner net watches for file changes, a builder net constructs artifacts, an analyzer net classifies results.
But what happens when the scanner discovers something the analyzer needs to classify? In traditional architectures, you’d wire up an HTTP callback, a message queue, or a shared database table. Each integration point is code you maintain, test, and debug. Each one is a potential failure mode.
We had a simpler idea: what if two nets just share a place?
The Idea: Same PlaceId, Same Token Pool
In AgenticOS, every place resolves to a path in the meta-filesystem: /root/workspace/places/{placeId}. This path is the same regardless of which net references it. If Net A’s postset writes to p-claude-result and Net B’s preset reads from p-claude-result, they’re accessing the exact same runtime container. No bridges. No adapters. Just a shared name.
The place appears in each net’s PNML definition (the visual model), but at runtime it resolves to one node in the tree. Tokens written by Net A’s transitions are immediately visible to Net B’s transitions. The meta-filesystem is the message bus.
The amber circle is the key: p-claude-result exists in both Net 1’s PNML (as a postset of the command transition) and Net 2’s PNML (as a preset of the classifier). At runtime, they resolve to the same node at /root/workspace/places/p-claude-result.
The Demo: Claude Code Runner → Issue Classifier
To prove this works, we built two nets in the same model (shared-places-demo) that communicate through a shared place:
Net 1: Claude Code Runner
This net takes a natural language task, transforms it into a shell command, and runs Claude Code in the agentic-nets/ working directory:
- p-task-input — Receives task tokens like
{"task": "List all TypeScript files in agentic-net-cli/src/agent/"} - t-map-to-cmd (map transition) — Transforms the task into a CommandToken with
claude -p '...' --dangerously-skip-permissions - t-run-claude (command transition) — Executes via the distributed executor, captures stdout
- p-claude-result — Output: the execution result with stdout, exit code, duration
Net 2: Issue Classifier
This net reads from the same p-claude-result place and classifies what Claude did:
- p-claude-result — The shared input (same placeId as Net 1’s output)
- t-classify (agent transition,
rw--) — An LLM agent that reads the execution result and classifies it into categories: bugfix, refactor, feature, docs, test, config, dependency, security, performance, other - p-classified-output — Receives structured classification tokens
Firing the Pipeline
We dropped a task token into p-task-input and fired each transition in sequence:
Step 1: Map Transition Transforms the Task
The map transition reads the task and produces a CommandToken — a structured JSON that the executor knows how to run:
<pre class="wp-block-syntaxhighlighter-code">{
"kind": "command",
"id": "claude-task-task-001",
"executor": "bash",
"command": "exec",
"args": {
"command": "claude -p 'List all TypeScript files in agentic-net-cli/src/agent/ and show the first 3 lines of each' --dangerously-skip-permissions --no-session-persistence < /dev/null",
"workingDir": "/Users/alexejsailer/Developer/AgenticOS/agentic-nets",
"timeoutMs": 120000
},
"expect": "text"
}</pre>
Step 2: Command Transition Executes Claude Code
The executor picks up the command token, runs Claude Code in the agentic-nets/ directory, and writes the result to p-claude-result — the shared place. Claude returned a clean markdown table of all 7 TypeScript files with their first 3 lines in about 18 seconds:
Here are the 7 TypeScript files in `agentic-net-cli/src/agent/`:
| File | Lines 1-3 |
|--------------------|-----------------------------------------------------|
| content-processor | /** Content processing utilities for EXTRACT... |
| runtime.ts | import type { LlmProvider } from '../llm/...' |
| transition-exec.ts | import type { LlmProvider } from '../llm/...' |
| prompts.ts | import { type AgentRole, getAvailableTools }... |
| tools.ts | /** Agent tools ported from AgentTool.java... |
| tool-executor.ts | import type { AgentTool } from './tools.js'... |
| roles.ts | import { AgentTool } from './tools.js'... |
Step 3: Agent Transition Classifies the Result
Now the magic: Net 2’s agent transition reads from the same place Net 1 wrote to. The LLM agent analyzed the Claude Code output and produced a classification token in p-classified-output:
{
"category": "other",
"confidence": "high",
"summary": "Claude executed a shell command to list TypeScript files and show their first 3 lines, providing a code structure overview without making any changes."
}
The full pipeline — from natural language task to classified result — crossed the net boundary through nothing more than a shared place name.
Discovering Shared Places: The New byName Index
A shared place only works if you can find it. Before this feature, answering “which places appear in multiple nets?” meant manually scanning every PNML definition. We solved this with a new byName index in the node service’s immutable read model.
The PublishedStructure — AgenticOS’s lock-free, immutable snapshot of all model data — now maintains three indexes:
byId— O(1) lookup by element UUID (existing)childrenByParent— O(1) child list by parent UUID (existing)byName— NEW: O(1) lookup of all elements sharing a name
The index is built during the commit phase — the same moment the other indexes are rebuilt. No extra I/O. One pointer per element in memory. The REST endpoint supports both exact match and glob patterns:
# Exact match
GET /api/models/shared-places-demo/search/byName?name=p-claude-result
# Glob pattern
GET /api/models/shared-places-demo/search/byName?name=p-*&pattern=glob
For p-claude-result, the response shows three matches — proving it exists in both PNMLs and the runtime:
{
"matchCount": 3,
"matches": [
{ "path": "/root/workspace/places/p-claude-result" },
{ "path": "/.../workspace-nets/claude-runner-net/pnml/net/places/p-claude-result" },
{ "path": "/.../workspace-nets/issue-classifier-net/pnml/net/places/p-claude-result" }
]
}
FIND_SHARED_PLACES: A First-Class Agent Tool
The byName search is the foundation, but the real power is in the FIND_SHARED_PLACES tool — available to agent transitions, the CLI, and the Telegram bot. It calls the master’s discovery endpoint, which groups name matches by location and identifies places that appear in multiple nets:
GET /api/assistant/universal/shared-places-demo/query/shared-places?namePattern=p-*
{
"totalShared": 4,
"sharedPlaces": [
{
"name": "p-claude-result",
"hasRuntimePlace": true,
"netCount": 2,
"nets": [
{ "netName": "claude-runner-net", "sessionId": "demo-session" },
{ "netName": "issue-classifier-net", "sessionId": "demo-session" }
]
}
]
}
An agent transition with the r flag can now call FIND_SHARED_PLACES to understand the cross-net topology before deciding where to route tokens. A builder agent can discover that p-claude-result is a communication bridge and avoid creating a duplicate place.
Why This Matters
Shared places turn multiple specialized nets into a composable system. Each net stays focused on one concern — running commands, classifying results, routing notifications — but they collaborate through shared token pools without any coupling code. The benefits compound:
- Zero integration code. No HTTP callbacks, no message queues, no event bus configuration. A shared placeId is the entire contract.
- Visual in the PNML. The GUI shows the shared place in both nets. You can see the data flow across net boundaries.
- Discoverable. The
FIND_SHARED_PLACEStool lets agents understand topology at runtime — not just follow static instructions. - Composable. Add a third net that also reads from
p-claude-result— say, a metrics collector. No changes to Net 1 or Net 2. - Token-level observability. Every token in the shared place has provenance — you know which transition produced it and which consumed it.
Try It Yourself
Create two nets with a shared place in any AgenticOS model:
# 1. Search for a place by name across the entire model
curl http://localhost:8080/api/models/YOUR_MODEL/search/byName?name=p-shared-place
# 2. Discover all shared places
curl http://localhost:8082/api/assistant/universal/YOUR_MODEL/query/shared-places
# 3. Use the agent tool in any agent transition or CLI session
FIND_SHARED_PLACES(namePattern: "p-*")
The pattern works with any number of nets and any transition types. If two inscriptions reference the same placeId, the tokens flow between them. That’s it. The meta-filesystem handles the rest.
Where This Leads
Shared places are the foundation for multi-net orchestration — semantically clustered nets that collaborate through shared token pools. The Obsidian Brain proved this at scale with 35 shared places across scanner, analyzer, and knowledge graph nets. With FIND_SHARED_PLACES now built into every agent interface, the next step is automated topology discovery: agents that can map cross-net communication patterns and suggest optimal place sharing strategies.
The meta-filesystem was always meant to be the universal data plane. Shared places make that concrete.
This article — including the demo nets, the shared place discovery feature, and the live pipeline test — was built in a single session using AgenticOS with Claude Code orchestrating the implementation across the node service (Java), master service (Java), and CLI (TypeScript).