solstone-think#
Post-processing utilities for clustering and summarising captured data. The tools leverage the Gemini API to analyse transcriptions and screenshots. All commands work with a journal directory that holds daily folders in YYYYMMDD format.
Installation#
make install
All dependencies are listed in pyproject.toml.
Usage#
The package exposes several commands:
sol call transcripts readgroups audio and screen transcripts into report sections. Use--startand--lengthto limit the report to a specific time range. Seesol call transcripts --helpfor additional commands.journal thinkruns generators and agents for a single day via Cortex.python -m solstone.think.talentsis the unified execution module for tool talents and generators spawned by Cortex (NDJSON protocol).journal supervisormonitors journaling health and starts the local services that feed Convey, Cortex, and related background tasks. Use the--no-*flags to opt out of specific services when debugging.journal cortexstarts a Callosum-based service for managing AI agent instances and generators.journal talentlists available agents and generators with their configuration. Usejournal talent show <name>to see details, andjournal talent show <name> --promptto see the fully composed prompt that would be sent to the LLM.
sol call transcripts read YYYYMMDD [--start HHMMSS --length MINUTES]
journal think [--day YYYYMMDD] [--segment HHMMSS_LEN] [--stream NAME] [--refresh] [--flush]
journal supervisor [--no-daily] [--no-cortex] [--no-spl] [--no-convey] [--no-schedule]
journal cortex [--host HOST] [--port PORT] [--path PATH]
journal talent list [--schedule daily|segment] [--json]
journal talent show <name> [--prompt] [--day YYYYMMDD] [--segment HHMMSS_LEN] [--full]
Use --refresh to overwrite existing files, and -v for verbose logs.
Set GOOGLE_API_KEY before running any command that contacts Gemini.
GOOGLE_API_KEY can also be provided in a .env file which
is loaded automatically by most commands.
Structured file importers are registered in solstone/think/importers/file_importer.py and
run through sol import's dispatcher. Their process() contract now accepts
dry_run: bool = False, and journal-archive imports use the same dispatcher
surface while serializing journal mutation with the merge lock contract.
Service Discovery#
Agents invoke tools through sol call shell commands:
sol call <module> <command> [args...].
Tool access is command-based via the sol call CLI framework.
Automating daily processing#
The journal think command can be triggered by a systemd timer. Below is a
minimal service and timer that process yesterday's folder every morning at
06:00:
[Unit]
Description=Process solstone journal
[Service]
Type=oneshot
ExecStart=/usr/local/bin/journal think
[Install]
WantedBy=multi-user.target
[Unit]
Description=Run journal think daily
[Timer]
OnCalendar=*-*-* 06:00:00
Persistent=true
Unit=sol-think.service
[Install]
WantedBy=timers.target
config/schedules.json contract#
config/schedules.json stores scheduler metadata and named schedule entries in
one top-level JSON object. Reserved metadata keys are daily_time, weekly_day,
and weekly_time; every other top-level key is a named entry with cmd and
every, plus optional enabled and max_runtime.
The scheduler's runtime reader, load_config, is forgiving: malformed entries
are skipped, reserved metadata is extracted separately, and invalid per-entry
data is not fatal. Writes go through solstone/think/schedule_config.py, the
sole write owner for the file. That owner is fail-visible for whole-file
malformation: malformed JSON or a non-object top-level value raises instead of
clobbering existing bytes.
Agent System#
Unified Priority Execution#
All scheduled prompts (both generators and tool-using agents) share a unified priority system. The journal think command executes prompts ordered by priority, from lowest (runs first) to highest (runs last).
Priority is required for all scheduled prompts. Prompts without a priority field will fail validation. Suggested priority bands:
| Band | Range | Use Case |
|---|---|---|
| Generators | 10-30 | Content-producing prompts that create .md files |
| Analysis Agents | 40-60 | Agents that analyze generated content |
| Late-stage | 90+ | Agents that run after most others complete |
| Fun/Optional | 99 | Low-priority or experimental prompts |
After each generator completes and creates output, the indexer runs --rescan-file for incremental indexing. A full --rescan runs in the post phase.
Cortex: Central Talent Manager#
The Cortex service (journal cortex) is the central system for managing AI talent instances and generators. It monitors the journal's talents/ directory for new requests and manages execution. All talent spawning should go through Cortex for proper event tracking and management.
Cortex routes requests based on configuration:
- Requests with
toolsfield → tool-using talents (python -m solstone.think.talents) - Requests with
outputfield (notools) → generators (python -m solstone.think.talents)
Both types are handled by the unified python -m solstone.think.talents execution module.
To spawn talents programmatically, use the cortex_client functions:
from solstone.think.cortex_client import cortex_request
from solstone.think.callosum import CallosumConnection
# Create a request
use_id = cortex_request(
prompt="Your task here",
name="default",
provider="openai" # or "google", "anthropic", "local"
)
# Watch for talent events via Callosum
def on_event(message):
# Filter for cortex tract events
if message.get('tract') != 'cortex':
return
print(f"Event: {message['event']}")
if message.get('event') == 'finish':
print(f"Result: {message.get('result')}")
watcher = CallosumConnection()
watcher.start(callback=on_event)
# ... later, when done:
watcher.stop()
Spawning Generators via Cortex#
Generators can also be spawned via cortex_request by including an output field:
from solstone.think.cortex_client import cortex_request, wait_for_uses
# Spawn a generator
use_id = cortex_request(
prompt="", # Generators don't use prompts
name="activity",
config={
"day": "20250109",
"output": "md",
"refresh": True, # Regenerate even if output exists
}
)
# Wait for completion
completed, timed_out = wait_for_uses([use_id], timeout=300)
Brain Health CLI#
Use journal brain status to inspect the active thinking lane and
journal brain refresh to run one bounded active-brain check:
journal brain status
journal brain refresh
Provider resolution lives in solstone/think/models.py. Generate and cogitate
share the single explicit providers.active provider/model selected in the
Thinking app. There is no key-presence fallback, tier override, backup route, or
talent-specific provider route. Configure cloud API keys in the env section of
journal/config/journal.json; the bundled local provider requires no API key.
Provider modules#
The registry in solstone/think/providers/__init__.py maps cloud provider names
to solstone/think/providers/openhands.py and maps local to
solstone/think/providers/local.py. Effective provider modules expose:
run_generate()- Sync text generation, returnsGenerateResultrun_agenerate()- Async text generation, returnsGenerateResultrun_cogitate()- Tool-calling execution viasol callcommands and event streaming
For direct LLM calls, use think.models.generate() or think.models.agenerate();
they route through the active brain.
Generator map keys#
think.talent.get_talent_configs(has_tools=False) reads the .md prompt files under solstone/talent/ and
returns a dictionary keyed by generator name. Each entry contains:
path– the prompt file pathcolor– UI color hex stringmtime– modification time of the.mdfile- Additional keys from JSON frontmatter such as
title,description,hook, orload
The hook field enables output processing by invoking named hooks like "schedule".
The load key controls transcript/percept/agent source filtering for generators.
See APPS.md for the full schema.
Cortex API#
Cortex is the central agent management system that all agent spawning should go through. See CORTEX.md for complete documentation of the Cortex API and agent event structures.
Using cortex_client#
The think.cortex_client module provides functions for interacting with Cortex:
from solstone.think.cortex_client import cortex_request, cortex_uses
# Create an agent request
request_file = cortex_request(
prompt="Your prompt",
name="default",
provider="openai"
)
# List running and completed agents
agents_info = cortex_uses(limit=10, use_type="live")
print(f"Found {agents_info['live_count']} running agents")
Talent Module#
AI agent system and tool-calling support for solstone.
Commands#
| Command | Purpose |
|---|---|
journal cortex |
Agent orchestration service |
journal brain status |
Active-brain thinking status |
journal brain refresh |
Bounded active-brain check |
Architecture#
Cortex (orchestrator)
├── Callosum connection (events)
├── Tool execution via `sol call`
└── Agent subprocess management
↓
Providers (openai, google, anthropic, local)
Providers#
| Provider | Module | Features |
|---|---|---|
| OpenAI | solstone/think/providers/openhands.py |
GPT models via OpenHands/LiteLLM |
solstone/think/providers/openhands.py |
Gemini models via OpenHands/LiteLLM | |
| Anthropic | solstone/think/providers/openhands.py |
Claude via OpenHands/LiteLLM |
| Local | solstone/think/providers/local.py |
Bundled llama-server, BYO OpenAI-compatible endpoint, and confidential local endpoint |
Effective provider modules implement run_generate(), run_agenerate(), and
run_cogitate() functions. Cloud vendor leaf modules implement generate only;
OpenHands owns cloud cogitate. See PROVIDERS.md for implementation
details.
Key Components#
- cortex.py - Central agent manager, file watcher, event distribution, spawns agents.py
- cortex_client.py - Client functions:
cortex_request(),cortex_uses(),wait_for_uses() - agents.py - Unified CLI entry point for both tool-using agents and generators (NDJSON protocol)
- models.py - Unified
generate()/agenerate()API, provider routing, token logging - batch.py -
Batchclass for concurrent LLM requests with dynamic queuing
Agent Personas#
System prompts in solstone/talent/*.md (markdown with JSON frontmatter). Apps can add custom agents in solstone/apps/{app}/talent/.
JSON metadata supports title, provider, model, tools, schedule, priority, multi_facet, and load keys. Cogitate prompts may set cwd: "journal"; when omitted they default to journal, and repo is rejected. Generators reject cwd.
Important: The priority field is required for all prompts with a schedule. Prompts without explicit priority will fail validation. See the Unified Priority Execution section for priority bands.
See APPS.md for the load schema and inline template variables that control source filtering and prompt context.
Documentation#
- PROVIDERS.md - Provider implementation guide
- CORTEX.md - Full API, event schemas, request format
- CALLOSUM.md - Message bus protocol
- THINK.md - Cortex usage examples