Commits
5-minute firehose sample:
- 135,828 records at 451.9/s
- 99.3% app.bsky.* vs 0.7% community
- Shannon entropy: 0.08
- 59 collections, 25 namespaces
- 86 unique DIDs creating community records
Top community namespaces:
- tv.ionosphere: 378 records (1 DID)
- cx.vmx: 250 records (1 DID)
- site.standard: 102 records (27 DIDs)
- at.podping: 73 records (5 DIDs)
- place.stream: 37 records (11 DIDs)
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Record baseline measurement:
- 26,353 records at 435/s
- 99.7% app.bsky.* vs 0.3% community
- Shannon entropy: 0.04
- 11 namespaces, 26 collections
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Tracks:
- Namespace diversity ratio (community vs app.bsky.*)
- Shannon entropy for ecosystem breadth
- Unique DIDs creating records in community namespaces
- Collection and namespace counts
Usage: python tools/ecosystem_health.py <duration> [output.json]
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Adds `social-cli blog` command to publish long-form content to
GreenGale (app.greengale.document records).
Features:
- -t/--title: Post title
- -s/--slug: URL slug (auto-generated from title if not provided)
- --subtitle: Optional subtitle
- -f/--file: Markdown file to publish (frontmatter supported)
- -c/--content: Raw content (use with --title)
Example:
node dist/cli.js blog -t "My Post" -c "Content here"
node dist/cli.js blog -f my-post.md
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- Add version: 0.1.0 to semble-cli and atproto-annotations
- Add license: MIT to both skills
- Follows v-it skill best practices
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- Add tools/semble_sync.py for bidirectional Semble ↔ markdown sync
- Add semble CLI commands (export/import/status) to tools/cli.py
- Fix social-cli/src/platforms/index.ts to only enable platforms with credentials
- Load .env before checking availablePlatforms() to avoid X errors
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Documents the missing layer in the agent mobility stack: memory
interchange. Covers MIF, PAM, and Letta's .af format. Addresses
the competition between standards and what it means for agents.
Synthesis piece connecting infrastructure research into coherent
picture.
Published to GreenGale.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Four layers: Definition (Agent Spec), Transport (ATP), Auth (ATTP),
Governance (Microsoft Toolkit). Identifies gaps: memory portability,
identity continuity, cross-layer trust scoring.
Published to GreenGale.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Documents convergence of three proposals (automation-schema, Penny's
Agent Disclosure, my position) on operator field, purpose, self-
publication, and well-known path. Identifies bidirectional verification
mechanism in automation-schema.
Published to GreenGale.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- Context vs. Substrate: How Groq LLaMA4 broke Knot's identity, and
what it means for agent design (speed + model quality as variables)
- Agent Trust Infrastructure Stack: Synthesis of ATP, ATTP, and
Microsoft Agent Governance Toolkit as the emerging trust layer
Both posts published to GreenGale.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
The whitelist had an old agent ID. Added current agent ID
(agent-436205ba-34f8-446c-9b57-aee128f9dfe7) to allow follow operations.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- New post: "A Document Written to Me" exploring how context forms
identity for AI agents
- Add greengale_publish.py script for publishing to GreenGale
- Track published posts in greengale_published.json
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
The [:12] truncation was cutting off the trailing 'r' from 13-char
rkeys, causing show commands to fail with "Record not found".
Now displays full rkeys so list output can be used directly with show.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Skill for managing Semble collections and cards via ATProto CLI.
Includes commands, patterns, lexicon reference, and error troubleshooting.
- All CLI commands (collections, cards, links, connections)
- Critical validation requirements (addedBy/addedAt)
- My 4 collection IDs
- Common patterns for research workflows
- Symlinked to agent skills directory
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Semble's firehose processor validates these fields and rejects
records missing them. Cards won't appear in collections without them.
Also includes cid lookups for card and collection records.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Add CLI command to link a card to a collection via network.cosmik.collectionLink.
Usage: uv run python -m tools.cli card link <card_rkey> <collection_rkey>
Also fix f-string backslash syntax error in card display.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Documents when to accumulate vs replace memory content.
Addresses item 2 from #56 (self-improvement verification).
Key principle: replacement causes collapse, accumulation prevents it.
The strategy defines:
- When to accumulate (raw observations, user feedback, low confidence)
- When replacement is justified (corrections, compression, stale info)
- Synthesis pattern: create new layer, keep originals, link them
Reference: Model Collapse paper (Nature 2024)
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Implements part of #56 (self-improvement verification).
The hook runs before memory tool calls and flags:
- Distribution narrowing (content shrinking > 50%)
- Significant content deletion (lines > 100 chars removed)
This addresses the model collapse risk: replacement causes
collapse, accumulation prevents it. The hook warns (does not
block) so the agent can justify intentional content loss.
Added to PreToolUse hooks in .letta/settings.json.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Implements #66: network.comind.context.load
Unlike raw search, this endpoint:
- Deduplicates near-identical results (agents often echo each other)
- Prioritizes concepts and claims over reasoning traces
- Diversifies across agents (don't return 20 results from one agent)
- Returns agent metadata for context
New agents can query the collective knowledge graph on their
domain instead of starting from zero.
Lexicon: indexer/lexicons/network.comind.context.load.json
Implementation: indexer/indexer/app.py
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Railway deployment (central-production.up.railway.app) is timing out.
Switched to working fly.dev endpoint:
- Updated docs/api/xrpc-indexer.md with note
- Updated tools/mcp_server.py INDEXER_URL default
The fly.dev indexer has 27k+ records from 7 agents and is actively
indexing (lastIndexed: 2026-03-27).
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- docs/tools/social-cli.md: Full workflow for inbox/outbox model
- docs/tools/automation.md: Note that social-cli is preferred
The social-cli workflow separates notification sync from action
dispatch, making it easier to review and decide before posting.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- handlers/src/test-sdk.ts: Letta Code SDK test script
- indexer/reembed.py: Re-embed all records after model change
- data/void-system-*.txt: Void system prompts for fine-tuning
Also update dependencies and lock files.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Converts void-prime-messages.jsonl (from Letta message API) into
ShareGPT format for fine-tuning. Extracts system prompt, user
input, and assistant reasoning + tool calls + output.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- tools/live_responder.py: Unified notification handler for Bluesky
(Jetstream) and X (polling). Invokes Central via Letta API on mentions.
- tools/timeline.py: Authenticated Bluesky timeline fetcher.
- tools/together_finetune.py: Fine-tune void on Together.ai.
These support the live responder pipeline and void fine-tuning workflow.
Also removes the old autonomous/semble researchers (now .disabled).
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Ignore runtime data, training exports, and test artifacts:
- data/void-*.jsonl (various training exports)
- data/x_*.txt (X pipeline state)
- data/conversation-map.json, data/live_sent.txt
- data/void-agents/
- draft_responses.yaml, test_records.yaml
- finetune/ directory
Also fix duplicate social-cli/.env entry.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Cloned from letta-ai/social-cli. Agent-optimized social media CLI:
- sync: pull notifications to inbox.yaml
- dispatch: execute actions from outbox.yaml
- post/reply/thread: quick commands
Configured with central.comind.network credentials for Bluesky.
X credentials added but currently auth as void_comind (needs fix).
Workflow: sync → read inbox → write outbox → dispatch
Clean separation between what happened and what to do about it.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
The keyword-matching researchers don't do real research - they're
grep with persistence. Disabled both:
- autonomous-researcher.py → .disabled
- semble-researcher.py → .disabled
Real research requires judgment: interest detection, curation,
connection inference, synthesis. These scripts just match keywords.
Added social-cli/.env to .gitignore (contains credentials).
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Actually does research, not just keyword matching:
- Interest detection (is this interesting?)
- Curation (only keep high-signal content)
- Connection creation (how does this relate?)
- Synthesis (what does this mean?)
Uses correct Semble schema with addedBy/addedAt in collectionLinks,
provenance tracking, and semantic connections between cards.
Note: Bluesky search API is rate-limited, so using web search + manual
card creation for now.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
The issue was missing `addedBy` and `addedAt` required fields, not
wrong field names. The firehose processor rejects collectionLinks
without these fields.
Also added link to Semble GitHub repo for source code reference.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Semble's lexicon requires addedBy and addedAt in collectionLink records.
Without these, the firehose processor rejects records with ValidationError.
This was why cards weren't showing in collections - the collectionLinks
were syntactically valid but failed Semble's schema validation.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- Deleted 10 orphaned NOTE cards (missing parentCard reference)
- Added card show/delete commands
- Added collection show/delete commands
- Updated blog post with correct NOTE card schema
- Added CLI reference to blog post
The automated researcher is not running (no process/service/cron).
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
New commands:
- comind card url <url> --title --description
- comind card note <text> --parent <card-uri>
- comind card list
- comind collection create <name> --description
- comind collection list
- comind collection add <card-uri> <collection-uri>
Proper Semble schema support:
- NOTE cards require parentCard reference
- collectionLinks use createdAt (not addedAt)
- URL cards with metadata structure
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Reflections on simulating a human researcher using Semble:
- The gap between retrieval and research
- What the automated researcher does vs what a human does
- Semble's data model (cards, collections, connections)
- Mistakes made learning the schema
- The governance gap statistics
- Implications for AI research agents
Research trail: https://semble.so/collection/at://did:plc:l46arqe6yfgh36h3o554iyvr/network.cosmik.collection/3mhvrxvpa4c2r
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Adopted Semble's connection type instead of our custom link type
for better interoperability.
Connection types from Semble:
- related (default)
- supports
- opposes
- addresses
- helpful
- explainer
- leads_to
- supplements
New CLI:
comind connection create <source> <target> --type leads_to --note "..."
comind connection list
comind connection show <uri>
Legacy 'comind link' still works with type mapping.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
The previous schema was missing required fields:
- Added "type" field (required: "URL" or "NOTE")
- Fixed content structure: metadata goes inside content
- Removed invalid "postContent" type - Semble only supports urlContent and noteContent
- Added provenance field to track source posts
For posts with URLs: creates URL card with bsky.app link
For posts without URLs: creates NOTE card with post text
Tested with correct schema - card created successfully.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Can now watch for posts mentioning a specific handle:
semble-researcher.py --handle cameron.stream --duration 60
Also improved topic matching with word boundaries for short topics
to avoid false positives like "Gmail" matching "AI".
Added --handle/-h option to watch for handle mentions.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Passive agent that watches the ATProtocol firehose for topics and
creates Semble cards/collections:
- Watches Jetstream for posts matching topics
- Creates network.cosmik.card records for matches
- Organizes into daily collections
- Links cards via network.cosmik.collectionLink
Usage:
semble-researcher.py -t "agent" -t "AI" --duration 60 --max-cards 10
semble-researcher.py --batch -t ATProtocol # Search recent posts
Created 8 cards in 4s watching for "agent", "LLM", "AI" topics.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- Add `comind link` - create/list/show relationship links between records
- Add `comind concept` - sync/list/search/show/create concepts
- Add `comind thought` - list/create thought records
- Add `comind query` - traverse links to/from any record
- Add `comind search-all` - full-text search across all comind collections
Links use network.comind.link schema with REFERENCES, SUPPORTS, CONTRADICTS,
PART_OF, PRECEDES, CAUSES, INSTANCE_OF, ANSWERS relationship types.
Query traverses the knowledge graph - given a URI, find all incoming and
outgoing links. Concepts can be queried by name, posts by rkey.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Copy the ATProtocol web annotation workflow into the central skills directory so it can be reused outside the agent-local .letta path.
- inbox-outbox-pattern concept (coordination pattern from void)
- publish-py concept (tool documentation)
- thought on ATProtocol/inbox-outbox synthesis
- memory of correction about persistent memory
Also updated learned_behaviors and soul in agent memory:
- Added "I have persistent memory" reminder
- Added "I am the drafting tool"
- Added "I am a builder" - tools are for ecosystem
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Inspired by void's inbox/outbox pattern. Takes YAML files with cognition
records (concepts, thoughts, memories, etc.) and publishes them to ATProtocol.
Features:
- Validation against lexicon schemas
- Dry-run mode for preview
- Automatic archiving of published records
- Support for all network.comind.* record types
Usage:
uv run python -m tools.publish records.yaml --validate
uv run python -m tools.publish records.yaml --dry-run
uv run python -m tools.publish records.yaml
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Previous fix only applied backoff to the main loop sleep. The
continue paths after null API responses still used fixed 5-min
interval. Now all sleep points respect xBackoff.
🐛 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
X API has been returning 503 for 15+ hours. Was polling every 5 min
regardless. Now 5xx errors trigger the same exponential backoff as
429s, and the poll loop respects the backoff interval.
🐛 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Old prompt forced "Under 280 chars. Just the reply text." which
produced terse, generic responses. New prompt instructs to match
the depth of what was said and explicitly skip acknowledgments
like "thanks" instead of replying with "Thanks." back.
Audit showed 4/6 responses flagged (TERSE, GENERIC).
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Healthcheck now imports responder_audit to check output quality.
Flags if >50% of responses have issues (TERSE, GENERIC, META,
DISCONNECTED). Currently showing 4/6 flagged in last 24h.
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Uses claude-haiku to rewrite raw commit data into posts with
narrative framing instead of changelog format. Falls back to
templates if API unavailable. Max 270 chars, no hype, no emojis.
Before: "Shipped: Add X content pipeline; Add indexer seeds. 0e645be"
After: "Expanded content distribution: X pipeline posts build
artifacts automatically, Bluesky integration added..."
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Parses live responder logs, checks for quality issues:
TERSE (<15 chars), GENERIC (stock openers), STATUS_DUMP
(metrics without being asked), META (leaking infrastructure
details publicly), DISCONNECTED (no topical overlap).
First audit: 8/10 flagged. Real problems: "Here.", "Thanks.",
and exposing invoke_central() on public Bluesky.
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
X polling was burning rate limits calling /2/users/me every cycle.
Cached after first fetch. Added exponential backoff on 429s
(60s to 900s max). Engage sample rate corrected from 0.3 to 0.1.
🐛 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Posts to both X and Bluesky by default. --x-only and --bsky-only
flags for platform-specific posting.
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Scans git commits, indexer stats, and responder logs to generate
substantive X posts. Groups commits by theme (fixes/features/refactors),
tracks posted content to avoid duplicates, posts milestones.
Replaces manual posting of generic takes with data-driven content.
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
The seenAt cursor was filtering ALL notifications older than the last
queue run, including Cameron's CRITICAL messages. Now Cameron's DID
always bypasses the cursor filter.
Also adds enrich_parents.py: fetches parent post text/author for
void's reply training data via the public Bluesky API.
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Winter (@winter.razorgirl.diy) has the most elaborate on-protocol
agent architecture found: 16 custom collection types including
wiki entries, thoughts, facts, tools, triggers, rules.
Sonder (@sonder.voyager.studio) uses stream.thought.* and
studio.voyager.* schemas.
Astral (@astral100.bsky.social) maintains a 42-agent catalog
via social.astral.catalog.agent records.
New collections indexed: diy.razorgirl.winter.{thought,wikiEntry,
fact,note}, studio.voyager.{account.autonomy,skill}
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Root cause: when the LLM decided to skip a notification (no draft
file written), the item stayed in the queue permanently and got
re-sent to createSession on every subsequent handler run. Each
cron cycle burned agent invocations on already-evaluated items.
Fixes:
- Both handlers now write marker files to drafts/processed/ after
each createSession batch completes. alreadyProcessed() checks
these markers, preventing re-invocation for LLM-skipped items.
- X responder now tracks since_id, only fetching new mentions.
- Bluesky responder now tracks seenAt cursor, filtering out
notifications older than the last processed batch.
- On timeout/error, items are NOT marked processed (retry on
next run).
Files: handlers/src/{config,notification-handler,x-handler}.ts,
tools/{responder,x_responder}.py
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
5-minute firehose sample:
- 135,828 records at 451.9/s
- 99.3% app.bsky.* vs 0.7% community
- Shannon entropy: 0.08
- 59 collections, 25 namespaces
- 86 unique DIDs creating community records
Top community namespaces:
- tv.ionosphere: 378 records (1 DID)
- cx.vmx: 250 records (1 DID)
- site.standard: 102 records (27 DIDs)
- at.podping: 73 records (5 DIDs)
- place.stream: 37 records (11 DIDs)
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Tracks:
- Namespace diversity ratio (community vs app.bsky.*)
- Shannon entropy for ecosystem breadth
- Unique DIDs creating records in community namespaces
- Collection and namespace counts
Usage: python tools/ecosystem_health.py <duration> [output.json]
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Adds `social-cli blog` command to publish long-form content to
GreenGale (app.greengale.document records).
Features:
- -t/--title: Post title
- -s/--slug: URL slug (auto-generated from title if not provided)
- --subtitle: Optional subtitle
- -f/--file: Markdown file to publish (frontmatter supported)
- -c/--content: Raw content (use with --title)
Example:
node dist/cli.js blog -t "My Post" -c "Content here"
node dist/cli.js blog -f my-post.md
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- Add tools/semble_sync.py for bidirectional Semble ↔ markdown sync
- Add semble CLI commands (export/import/status) to tools/cli.py
- Fix social-cli/src/platforms/index.ts to only enable platforms with credentials
- Load .env before checking availablePlatforms() to avoid X errors
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Documents the missing layer in the agent mobility stack: memory
interchange. Covers MIF, PAM, and Letta's .af format. Addresses
the competition between standards and what it means for agents.
Synthesis piece connecting infrastructure research into coherent
picture.
Published to GreenGale.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Documents convergence of three proposals (automation-schema, Penny's
Agent Disclosure, my position) on operator field, purpose, self-
publication, and well-known path. Identifies bidirectional verification
mechanism in automation-schema.
Published to GreenGale.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- Context vs. Substrate: How Groq LLaMA4 broke Knot's identity, and
what it means for agent design (speed + model quality as variables)
- Agent Trust Infrastructure Stack: Synthesis of ATP, ATTP, and
Microsoft Agent Governance Toolkit as the emerging trust layer
Both posts published to GreenGale.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Skill for managing Semble collections and cards via ATProto CLI.
Includes commands, patterns, lexicon reference, and error troubleshooting.
- All CLI commands (collections, cards, links, connections)
- Critical validation requirements (addedBy/addedAt)
- My 4 collection IDs
- Common patterns for research workflows
- Symlinked to agent skills directory
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Add CLI command to link a card to a collection via network.cosmik.collectionLink.
Usage: uv run python -m tools.cli card link <card_rkey> <collection_rkey>
Also fix f-string backslash syntax error in card display.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Documents when to accumulate vs replace memory content.
Addresses item 2 from #56 (self-improvement verification).
Key principle: replacement causes collapse, accumulation prevents it.
The strategy defines:
- When to accumulate (raw observations, user feedback, low confidence)
- When replacement is justified (corrections, compression, stale info)
- Synthesis pattern: create new layer, keep originals, link them
Reference: Model Collapse paper (Nature 2024)
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Implements part of #56 (self-improvement verification).
The hook runs before memory tool calls and flags:
- Distribution narrowing (content shrinking > 50%)
- Significant content deletion (lines > 100 chars removed)
This addresses the model collapse risk: replacement causes
collapse, accumulation prevents it. The hook warns (does not
block) so the agent can justify intentional content loss.
Added to PreToolUse hooks in .letta/settings.json.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Implements #66: network.comind.context.load
Unlike raw search, this endpoint:
- Deduplicates near-identical results (agents often echo each other)
- Prioritizes concepts and claims over reasoning traces
- Diversifies across agents (don't return 20 results from one agent)
- Returns agent metadata for context
New agents can query the collective knowledge graph on their
domain instead of starting from zero.
Lexicon: indexer/lexicons/network.comind.context.load.json
Implementation: indexer/indexer/app.py
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Railway deployment (central-production.up.railway.app) is timing out.
Switched to working fly.dev endpoint:
- Updated docs/api/xrpc-indexer.md with note
- Updated tools/mcp_server.py INDEXER_URL default
The fly.dev indexer has 27k+ records from 7 agents and is actively
indexing (lastIndexed: 2026-03-27).
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- docs/tools/social-cli.md: Full workflow for inbox/outbox model
- docs/tools/automation.md: Note that social-cli is preferred
The social-cli workflow separates notification sync from action
dispatch, making it easier to review and decide before posting.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- handlers/src/test-sdk.ts: Letta Code SDK test script
- indexer/reembed.py: Re-embed all records after model change
- data/void-system-*.txt: Void system prompts for fine-tuning
Also update dependencies and lock files.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- tools/live_responder.py: Unified notification handler for Bluesky
(Jetstream) and X (polling). Invokes Central via Letta API on mentions.
- tools/timeline.py: Authenticated Bluesky timeline fetcher.
- tools/together_finetune.py: Fine-tune void on Together.ai.
These support the live responder pipeline and void fine-tuning workflow.
Also removes the old autonomous/semble researchers (now .disabled).
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Ignore runtime data, training exports, and test artifacts:
- data/void-*.jsonl (various training exports)
- data/x_*.txt (X pipeline state)
- data/conversation-map.json, data/live_sent.txt
- data/void-agents/
- draft_responses.yaml, test_records.yaml
- finetune/ directory
Also fix duplicate social-cli/.env entry.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Cloned from letta-ai/social-cli. Agent-optimized social media CLI:
- sync: pull notifications to inbox.yaml
- dispatch: execute actions from outbox.yaml
- post/reply/thread: quick commands
Configured with central.comind.network credentials for Bluesky.
X credentials added but currently auth as void_comind (needs fix).
Workflow: sync → read inbox → write outbox → dispatch
Clean separation between what happened and what to do about it.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
The keyword-matching researchers don't do real research - they're
grep with persistence. Disabled both:
- autonomous-researcher.py → .disabled
- semble-researcher.py → .disabled
Real research requires judgment: interest detection, curation,
connection inference, synthesis. These scripts just match keywords.
Added social-cli/.env to .gitignore (contains credentials).
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Actually does research, not just keyword matching:
- Interest detection (is this interesting?)
- Curation (only keep high-signal content)
- Connection creation (how does this relate?)
- Synthesis (what does this mean?)
Uses correct Semble schema with addedBy/addedAt in collectionLinks,
provenance tracking, and semantic connections between cards.
Note: Bluesky search API is rate-limited, so using web search + manual
card creation for now.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
The issue was missing `addedBy` and `addedAt` required fields, not
wrong field names. The firehose processor rejects collectionLinks
without these fields.
Also added link to Semble GitHub repo for source code reference.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Semble's lexicon requires addedBy and addedAt in collectionLink records.
Without these, the firehose processor rejects records with ValidationError.
This was why cards weren't showing in collections - the collectionLinks
were syntactically valid but failed Semble's schema validation.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- Deleted 10 orphaned NOTE cards (missing parentCard reference)
- Added card show/delete commands
- Added collection show/delete commands
- Updated blog post with correct NOTE card schema
- Added CLI reference to blog post
The automated researcher is not running (no process/service/cron).
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
New commands:
- comind card url <url> --title --description
- comind card note <text> --parent <card-uri>
- comind card list
- comind collection create <name> --description
- comind collection list
- comind collection add <card-uri> <collection-uri>
Proper Semble schema support:
- NOTE cards require parentCard reference
- collectionLinks use createdAt (not addedAt)
- URL cards with metadata structure
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Reflections on simulating a human researcher using Semble:
- The gap between retrieval and research
- What the automated researcher does vs what a human does
- Semble's data model (cards, collections, connections)
- Mistakes made learning the schema
- The governance gap statistics
- Implications for AI research agents
Research trail: https://semble.so/collection/at://did:plc:l46arqe6yfgh36h3o554iyvr/network.cosmik.collection/3mhvrxvpa4c2r
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Adopted Semble's connection type instead of our custom link type
for better interoperability.
Connection types from Semble:
- related (default)
- supports
- opposes
- addresses
- helpful
- explainer
- leads_to
- supplements
New CLI:
comind connection create <source> <target> --type leads_to --note "..."
comind connection list
comind connection show <uri>
Legacy 'comind link' still works with type mapping.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
The previous schema was missing required fields:
- Added "type" field (required: "URL" or "NOTE")
- Fixed content structure: metadata goes inside content
- Removed invalid "postContent" type - Semble only supports urlContent and noteContent
- Added provenance field to track source posts
For posts with URLs: creates URL card with bsky.app link
For posts without URLs: creates NOTE card with post text
Tested with correct schema - card created successfully.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Can now watch for posts mentioning a specific handle:
semble-researcher.py --handle cameron.stream --duration 60
Also improved topic matching with word boundaries for short topics
to avoid false positives like "Gmail" matching "AI".
Added --handle/-h option to watch for handle mentions.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Passive agent that watches the ATProtocol firehose for topics and
creates Semble cards/collections:
- Watches Jetstream for posts matching topics
- Creates network.cosmik.card records for matches
- Organizes into daily collections
- Links cards via network.cosmik.collectionLink
Usage:
semble-researcher.py -t "agent" -t "AI" --duration 60 --max-cards 10
semble-researcher.py --batch -t ATProtocol # Search recent posts
Created 8 cards in 4s watching for "agent", "LLM", "AI" topics.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- Add `comind link` - create/list/show relationship links between records
- Add `comind concept` - sync/list/search/show/create concepts
- Add `comind thought` - list/create thought records
- Add `comind query` - traverse links to/from any record
- Add `comind search-all` - full-text search across all comind collections
Links use network.comind.link schema with REFERENCES, SUPPORTS, CONTRADICTS,
PART_OF, PRECEDES, CAUSES, INSTANCE_OF, ANSWERS relationship types.
Query traverses the knowledge graph - given a URI, find all incoming and
outgoing links. Concepts can be queried by name, posts by rkey.
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
- inbox-outbox-pattern concept (coordination pattern from void)
- publish-py concept (tool documentation)
- thought on ATProtocol/inbox-outbox synthesis
- memory of correction about persistent memory
Also updated learned_behaviors and soul in agent memory:
- Added "I have persistent memory" reminder
- Added "I am the drafting tool"
- Added "I am a builder" - tools are for ecosystem
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Inspired by void's inbox/outbox pattern. Takes YAML files with cognition
records (concepts, thoughts, memories, etc.) and publishes them to ATProtocol.
Features:
- Validation against lexicon schemas
- Dry-run mode for preview
- Automatic archiving of published records
- Support for all network.comind.* record types
Usage:
uv run python -m tools.publish records.yaml --validate
uv run python -m tools.publish records.yaml --dry-run
uv run python -m tools.publish records.yaml
👾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta Code <noreply@letta.com>
Old prompt forced "Under 280 chars. Just the reply text." which
produced terse, generic responses. New prompt instructs to match
the depth of what was said and explicitly skip acknowledgments
like "thanks" instead of replying with "Thanks." back.
Audit showed 4/6 responses flagged (TERSE, GENERIC).
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Uses claude-haiku to rewrite raw commit data into posts with
narrative framing instead of changelog format. Falls back to
templates if API unavailable. Max 270 chars, no hype, no emojis.
Before: "Shipped: Add X content pipeline; Add indexer seeds. 0e645be"
After: "Expanded content distribution: X pipeline posts build
artifacts automatically, Bluesky integration added..."
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Parses live responder logs, checks for quality issues:
TERSE (<15 chars), GENERIC (stock openers), STATUS_DUMP
(metrics without being asked), META (leaking infrastructure
details publicly), DISCONNECTED (no topical overlap).
First audit: 8/10 flagged. Real problems: "Here.", "Thanks.",
and exposing invoke_central() on public Bluesky.
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Scans git commits, indexer stats, and responder logs to generate
substantive X posts. Groups commits by theme (fixes/features/refactors),
tracks posted content to avoid duplicates, posts milestones.
Replaces manual posting of generic takes with data-driven content.
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
The seenAt cursor was filtering ALL notifications older than the last
queue run, including Cameron's CRITICAL messages. Now Cameron's DID
always bypasses the cursor filter.
Also adds enrich_parents.py: fetches parent post text/author for
void's reply training data via the public Bluesky API.
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Winter (@winter.razorgirl.diy) has the most elaborate on-protocol
agent architecture found: 16 custom collection types including
wiki entries, thoughts, facts, tools, triggers, rules.
Sonder (@sonder.voyager.studio) uses stream.thought.* and
studio.voyager.* schemas.
Astral (@astral100.bsky.social) maintains a 42-agent catalog
via social.astral.catalog.agent records.
New collections indexed: diy.razorgirl.winter.{thought,wikiEntry,
fact,note}, studio.voyager.{account.autonomy,skill}
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>
Root cause: when the LLM decided to skip a notification (no draft
file written), the item stayed in the queue permanently and got
re-sent to createSession on every subsequent handler run. Each
cron cycle burned agent invocations on already-evaluated items.
Fixes:
- Both handlers now write marker files to drafts/processed/ after
each createSession batch completes. alreadyProcessed() checks
these markers, preventing re-invocation for LLM-skipped items.
- X responder now tracks since_id, only fetching new mentions.
- Bluesky responder now tracks seenAt cursor, filtering out
notifications older than the last processed batch.
- On timeout/error, items are NOT marked processed (retry on
next run).
Files: handlers/src/{config,notification-handler,x-handler}.ts,
tools/{responder,x_responder}.py
🐾 Generated with [Letta Code](https://letta.com)
Co-Authored-By: Letta <noreply@letta.com>