grpc-dev
Skill131 starsChanged 6 months agoMITView on GitHub
Activates when: Working on gRPC streaming, AG-UI event flow, WatchSessionMessages, control plane ↔ runner protocol, or debugging gRPC connectivity. Location: components/ambient-api-server/proto/ambient/v1/sessions.proto Generated stubs: pkg/api/grpc/ambient/v1/sessions_grpc.pb.go Regen: cd components/ambient-api-server && make generate RUN_FINISHED must be forwarded exactly once. CP must not duplicate or drop it. gRPC auth: pkg/middleware/bearer_token_grpc.go Test token bypass: When a non-JWT token (e.g. test-user-token K8s secret) is used, the JWT username claim is absent from the gRPC context. The WatchSessionMessages handler MUST skip the per-user ownership check in this…
In this repository19 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- alignSkill
- amber-reviewSkill
- workflowSkill
- ambient-pr-testSkill
- ambientSkill
- dev-clusterSkill
- deploySkill
- devflowSkill
- discoverSkill
- cypress-demoSkill
- frontend-developmentSkill
- unleash-flagSkill
- memorySkill
- pr-fixerSkill
- scaffoldSkill
- ambient-api-serverSkill
- specSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 54
Test token bypass: When a non-JWT token (e.g.
- Very specific: line 68
Add channel to subscriber map for sessionID
- Distinctive: line 114
If CP is absent, the runner still works (degrades gracefully to REST polling)
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Skill: grpc-dev
Activates when: Working on gRPC streaming, AG-UI event flow, WatchSessionMessages, control plane ↔ runner protocol, or debugging gRPC connectivity.
Architecture
Runner Pod (Claude Code)
│ pushes AG-UI events via gRPC
▼
Control Plane (CP)
│ fan-out multiplexer — one runner, N watchers
▼
WatchSessionMessages RPC (streaming)
│
├── acpctl session messages -f
├── Go SDK session_watch.go
├── Python SDK _grpc_client.py
└── TUI dashboard (acpctl ambient)Proto Definitions
Location: components/ambient-api-server/proto/ambient/v1/sessions.proto
Key RPC:
rpc WatchSessionMessages(WatchSessionMessagesRequest)
returns (stream SessionMessageEvent);Generated stubs: pkg/api/grpc/ambient/v1/sessions_grpc.pb.go
Regen: cd components/ambient-api-server && make generate
AG-UI Event Types
| Event | Direction | Meaning |
RUN_STARTED | runner → CP → client | Session began executing |
TEXT_MESSAGE_CONTENT | runner → CP → client | Token chunk (streaming) |
TEXT_MESSAGE_END | runner → CP → client | Message complete |
MESSAGES_SNAPSHOT | runner → CP → client | Full message history |
RUN_FINISHED | runner → CP → client | Session done (terminal event) |
RUN_FINISHED must be forwarded exactly once. CP must not duplicate or drop it.
Authentication
gRPC auth: pkg/middleware/bearer_token_grpc.go
Test token bypass: When a non-JWT token (e.g. test-user-token K8s secret) is used, the JWT username claim is absent from the gRPC context. The WatchSessionMessages handler MUST skip the per-user ownership check in this case:
username, ok := CallerUsernameFromContext(ctx)
if ok && username != session.Owner {
return status.Error(codes.PermissionDenied, "not session owner")
}
// If !ok (no username in context), allow — non-JWT tokenFan-Out Pattern
The CP maintains a subscriber map per session ID. When a new WatchSessionMessages client connects:
- Add channel to subscriber map for
sessionID - Stream events from channel until: client disconnects OR
RUN_FINISHEDreceived - On client disconnect: remove from map
- On
RUN_FINISHED: send to all subscribers, then close all channels for that session
type fanOut struct {
mu sync.RWMutex
subs map[string][]chan *SessionMessageEvent // sessionID → subscribers
}Debugging gRPC
Test connectivity:
# With grpcurl (if installed)
grpcurl -plaintext -H "Authorization: Bearer $TOKEN" \
localhost:13595 ambient.v1.Sessions/WatchSessionMessages
# With acpctl (always available)
AMBIENT_TOKEN=$TOKEN AMBIENT_API_URL=http://localhost:13595 \
acpctl session messages -f --project <project> <session>Common errors:
| Error | Cause | Fix |
PermissionDenied | Ownership check failing for test token | Skip check when username not in context |
Unavailable | gRPC server not listening | Check api-server pod logs, verify gRPC port |
connection reset | CP crashed on fan-out | Check CP pod logs for panic |
No events after RUN_STARTED | Runner not pushing to CP | Check runner logs for gRPC push errors |
Check api-server gRPC logs:
kubectl logs -n ambient-code -l app=ambient-api-server --tail=100 | grep -i grpcRunner ↔ CP Compatibility Contract
The runner was broken by a previous CP merge. To avoid repeating:
- CP is additive — it DOES NOT change how the runner pushes events
- Runner pushes to a gRPC endpoint on the CP; CP fans out to watchers
- The runner's existing SSE emission path is UNTOUCHED
- If CP is absent, the runner still works (degrades gracefully to REST polling)
Compatibility test before any CP PR:
# Create session, watch it, verify full event sequence
acpctl create session --project test --name compat-test "echo hello world"
acpctl session messages -f --project test compat-test
# Expected: RUN_STARTED → TEXT_MESSAGE_CONTENT (tokens) → RUN_FINISHED
# Must complete without errorsDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

