SSyncropel Docs

Configuration

Engine configuration — routing rules, event triggers, and server settings.

Configuration File

Syncropel stores local settings in ~/.syncro/config.toml:

[identity]
actor = "did:sync:user:alice"
display_name = "Alice"

[store]
url = "sqlite:///home/alice/.syncro/hub.db"

[server]
host = "127.0.0.1"
port = 9100

View the configuration:

spl config show
spl config path    # Shows the file location

Engine Configuration

Engine behavior is configured through records on a special thread. This means configuration is versioned, auditable, and can change at runtime.

Routing Rules

# Add a routing rule
spl config add-rule \
  --name "code-to-dev" \
  --domain code \
  --act INTEND \
  --target did:sync:agent:dev

# List rules
spl config list-rules

Rules are evaluated in order. The first matching rule determines where a record is routed.

Event Triggers

Event triggers wake up actors when specific records appear:

# Create a trigger
spl config add-trigger \
  --name "review-on-completion" \
  --match "act=KNOW,body.topic=task_completion" \
  --target did:sync:agent:reviewer \
  --goal "Review the completed task" \
  --budget 1.0 \
  --timeout 300 \
  --cooldown 60

# Create a scheduled trigger
spl config add-trigger \
  --name "daily-summary" \
  --schedule "0 9 * * *" \
  --target did:sync:agent:reporter \
  --goal "Generate daily project summary"

# List triggers
spl config list-triggers

# Disable a trigger
spl config add-trigger --name "review-on-completion" --disable

Trigger options:

FlagDefaultDescription
--matchRecord pattern: "act=KNOW,body.topic=task_verdict"
--scheduleCron expression: "*/15 * * * *" (mutually exclusive with match)
--targetActor DID to dispatch to
--goalGoal text for the dispatched actor
--budget1.0Maximum cost per dispatch (USD)
--timeout300Maximum duration per dispatch (seconds)
--cooldown60Minimum seconds between fires
--max-concurrent1Maximum simultaneous dispatches from this trigger

API Keys

# Set an AI provider key
spl config set-key anthropic sk-ant-...

# Set the default model
spl config model claude-sonnet-4-20250514

Authentication

Bearer-token authentication for spl serve is governed by two config surfaces:

1. Server-side toggle — a LEARN record on th_engine_config:

# Enable enforcement
spl learn \
  --thread th_engine_config \
  --body '{"topic":"auth_required","enabled":true}' \
  --actor did:sync:system:engine
FieldTypeDefaultDescription
topicstringMust be "auth_required"
enabledboolfalseWhen true, every non-exempt endpoint requires Authorization: Bearer <token>

Exempt routes (always unauthenticated): GET /health, POST /v1/bootstrap/service-account, GET /.well-known/syncropel.

The daemon reloads th_engine_config on broadcast, so new records take effect on the next request — no restart needed.

2. CORS allow-list — a separate LEARN record:

spl learn \
  --thread th_engine_config \
  --body '{"topic":"auth_cors_origins","origins":["https://your-app.example.com"]}' \
  --actor did:sync:system:engine

CORS headers are sent only when auth.required = true. With auth off, CORS is permissive by default.

3. Escape hatchspl serve --insecure-localhost force-binds the daemon to 127.0.0.1 and disables auth enforcement, regardless of the auth.required setting. Used for emergency recovery when tokens are lost. A WARN log is emitted on every startup when this flag is active. Never use in production.

See the Authentication & Service Accounts guide for the full workflow — first-SA bootstrap, token lifecycle, federation pairing, and emergency recovery.

Embedding provider

Configure the provider used for semantic search. Without a provider, POST /v1/records/search returns 503 SEMANTIC_SEARCH_DISABLED and spl search surfaces a disabled: true flag instead of raising.

Managed via spl config embedding-provider set|show|clear (see the CLI reference). Both commands write a LEARN record on th_engine_config; the daemon rebuilds its embedder on broadcast — no restart.

spl learn \
  --thread th_engine_config \
  --body '{"topic":"embedding_provider","provider":{"kind":"ollama","endpoint":"http://localhost:11434","model":"nomic-embed-text"}}' \
  --actor did:sync:system:engine
FieldTypeDefaultDescription
topicstringMust be "embedding_provider"
providerobject | nullnullProvider config. Set null to clear (disables semantic search while retaining stored vectors)
provider.kindstringProvider kind. Currently only "ollama"
provider.endpointstring"http://localhost:11434"HTTP endpoint of the embedding service (Ollama)
provider.modelstring"nomic-embed-text"Model name. Changing the model is a "different embedder" — old vectors become inactive (retained but unused until cleared)

After enabling a provider, backfill existing records with spl embed --loop (or POST /v1/records/embed in a shell loop). New records are embedded inline by the INGEST loop.

Async-federation relay

Configure one or more store-and-forward relays for async federation — used when peers aren't reliably online at the same time. Each entry binds a relay URL to either a specific peer DID or the catch-all sentinel "all". An entry with enabled: false is kept so an operator can toggle without losing the URL.

Managed via spl config relay set|show|status|clear (see the CLI reference). Each mutating subcommand writes a LEARN record:

spl learn \
  --thread th_engine_config \
  --body '{"topic":"federation.relay","url":"https://relay.syncropel.com","for_pair":"all","enabled":true}' \
  --actor did:sync:system:engine
FieldTypeDefaultDescription
topicstringMust be "federation.relay"
urlstringRelay base URL (no trailing slash required)
for_pairstringPeer DID this relay is for, or the sentinel "all" as the catch-all
enabledbooltrueWhen false, the entry is preserved but skipped at lookup time

At send time, lookup proceeds most-specific-first: an exact for_pair == peer_did match wins; otherwise the "all" catch-all is used. Inbound receive tasks spawn at daemon startup — restart spl serve after configuring a new relay URL so the receive loop binds.

Responder overrides

Responder metadata is auto-populated from live adapters and the actor registry, then merged with operator overrides at serve time. Overrides let you curate the responders advertised on /v1/capabilities and /.well-known/syncropel — set a cost model, pin a trust floor, tombstone a responder from the manifest, or introduce an operator-authored responder that has no auto-populated entry.

Managed via spl config responders-add|responders-list|responders-remove (see the CLI reference). Each mutating subcommand writes a LEARN record with topic: "responder_override":

spl learn \
  --thread th_engine_config \
  --body '{
    "topic":"responder_override",
    "did":"did:sync:agent:dev",
    "kind":"actor",
    "capabilities":["code","shell"],
    "trust_floor":{"code":0.75},
    "cost_model":{"per_query_usd":0.04}
  }' \
  --actor did:sync:system:engine
FieldTypeDescription
topicstringMust be "responder_override"
didstringTarget responder DID. Required
kindstring | nullactor, llm, pattern, or system. Absent ⇒ defer to auto-populated value
capabilitieslist<string> | nullReplaces the capability list for this DID
trust_floorobject | nullFree-form trust-floor object (e.g. {"code": 0.75})
cost_modelobject | nullFree-form cost-model object (e.g. {"per_query_usd": 0.04})
availabilityobject | nullFree-form availability object (e.g. {"timezone": "PST"})
metadataobject | nullFree-form metadata. Non-normative
removeboolWhen true, tombstone this responder — suppress it from the manifest even if an auto-populated entry exists

Overrides matched by DID replace the auto-populated entry's fields in place; unmatched DIDs are appended as operator-authored responders. The override schema ships today; consumers that route on responder metadata will arrive in a later release.

Data Locations

PathPurpose
~/.syncro/config.tomlLocal settings (identity, server, store)
~/.syncro/hub.dbRecord database (SQLite)
~/.syncro/secrets/API keys (plaintext files)
~/.syncro-data/tasks/Task content files (Markdown)
~/.syncro-data/aliases.tomlTask alias mappings
~/.local/share/syncropel/backups/Automatic database backups

On this page