Research, evidence, and social handoff

Let external apps ask for content, require proof, commit public-safe state, and read it back.

LoreOS Core can help a Social Presence or Lore Creators app decide whether a desired post fits a character’s current state. It does not write captions, publish posts, or pretend a character visited somewhere without evidence.

The boundary is:

Social app proposes a content goal
-> LoreOS checks fit and evidence requirements
-> human/operator evidence can be submitted
-> review and commit materialize public-safe character state
-> Social app reads the public slice
-> Social app writes captions/posts using only claim-safe facts

What LoreOS does

  • Accepts content intents from an external app.
  • Returns deterministic fit feedback and missing evidence requirements.
  • Creates mission candidates for a human/operator to verify.
  • Stores research, field, brand, receipt, or published-post evidence.
  • Gates evidence before it becomes character state.
  • Exposes a public slice for downstream social planning.

What the Social app does

  • Chooses the channel, format, creative angle, cadence, and publish workflow.
  • Collects field evidence from the human operator.
  • Generates captions, reels, stories, thumbnails, and approvals.
  • Handles brand disclosures, usage rights, payouts, and Instagram publishing.

Key boundary

Research is not lived memory. A mission is not a visit. A published post is not proof of a visit. First-person experience claims need first-hand or receipt-backed evidence. POST /v1/characters/{slug}/published-posts records publication only; it rejects claim_basis=first_hand_visit and claim_basis=receipt_verified.

Public API flow

This is the externally supported flow. Use your own character slug from the Quickstart.

$export LOREOS_BASE="${LOREOS_BASE:-https://api.loreos.app}"
$export LOREOS_KEY="ck_..."
$export CHARACTER_SLUG="yura"

1. Submit a content intent

$INTENT_JSON="$(curl -sS -X POST "$LOREOS_BASE/v1/characters/$CHARACTER_SLUG/content-intents" \
> -H "Authorization: Bearer $LOREOS_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "intent_type": "instagram_post",
> "title": "Cafe A visit post",
> "desired_outcome": "Publish a grounded first-hand cafe post.",
> "target_audience": "local cafe fans",
> "content_brief": "Show a verified cafe visit through the character point of view.",
> "target_entities": [{"type": "place", "name": "Cafe A"}],
> "required_claims": [{"claim": "The character visited Cafe A"}],
> "evidence_requirements": [{"claim_basis": "first_hand_visit"}]
> }')"
$INTENT_ID="$(printf '%s' "$INTENT_JSON" | jq -r '.data.content_intent.id')"

2. Check fit before evidence exists

$curl -sS -X POST "$LOREOS_BASE/v1/characters/$CHARACTER_SLUG/content-intents/$INTENT_ID/fit" \
> -H "Authorization: Bearer $LOREOS_KEY" \
> -H "Content-Type: application/json" \
> -d '{"create_mission_hint": true}' | jq '.data.fit_result'

Expected shape:

1{
2 "fit_status": "needs_evidence",
3 "needs": ["verified_evidence_for_required_claims", "field_or_receipt_evidence"],
4 "mission_recommendation": {
5 "mission_type": "field_verification"
6 }
7}

3. Create an operator mission

$MISSION_JSON="$(curl -sS -X POST "$LOREOS_BASE/v1/characters/$CHARACTER_SLUG/mission-candidates" \
> -H "Authorization: Bearer $LOREOS_KEY" \
> -H "Content-Type: application/json" \
> -d "{
> \"mission_type\": \"field_verification\",
> \"title\": \"Verify Cafe A\",
> \"reason\": \"First-hand evidence is required before a visit claim.\",
> \"source_content_intent_id\": \"$INTENT_ID\",
> \"target\": {\"type\": \"place\", \"name\": \"Cafe A\"},
> \"required_evidence\": [{\"claim_basis\": \"first_hand_visit\"}]
> }")"
$MISSION_ID="$(printf '%s' "$MISSION_JSON" | jq -r '.data.mission_candidate.id')"

4. Submit verified field evidence

In production, this should come from the human/operator evidence form: photos, notes, receipt or location proof when available, and structured observations. The example below shows the API shape.

$EVIDENCE_JSON="$(curl -sS -X POST "$LOREOS_BASE/v1/characters/$CHARACTER_SLUG/evidence" \
> -H "Authorization: Bearer $LOREOS_KEY" \
> -H "Content-Type: application/json" \
> -d "{
> \"evidence_kind\": \"field_evidence\",
> \"claim_basis\": \"first_hand_visit\",
> \"verification_status\": \"verified\",
> \"confidence\": 0.93,
> \"title\": \"Cafe A field visit\",
> \"summary\": \"The operator visited Cafe A and verified it as a quiet lunch spot.\",
> \"source_provider\": \"operator\",
> \"extracted_claims\": [{\"claim\": \"Cafe A was visited first-hand\"}],
> \"content\": {
> \"target_type\": \"place\",
> \"source_mission_id\": \"$MISSION_ID\",
> \"structured_observations\": {\"crowd_level\": \"quiet\"}
> },
> \"public_eligible\": true,
> \"usable_in_chat\": true,
> \"usable_in_social\": true
> }")"
$EVIDENCE_ID="$(printf '%s' "$EVIDENCE_JSON" | jq -r '.data.evidence.id')"

5. Re-check fit

$curl -sS -X POST "$LOREOS_BASE/v1/characters/$CHARACTER_SLUG/content-intents/$INTENT_ID/fit" \
> -H "Authorization: Bearer $LOREOS_KEY" \
> -H "Content-Type: application/json" \
> -d "{\"candidate_evidence_ids\": [\"$EVIDENCE_ID\"]}" | jq '.data.fit_result.fit_status'

Expected: "story_fit_possible".

6. Move evidence through state review

$CANDIDATE_JSON="$(curl -sS -X POST "$LOREOS_BASE/v1/characters/$CHARACTER_SLUG/evidence/$EVIDENCE_ID/state-candidate" \
> -H "Authorization: Bearer $LOREOS_KEY" \
> -H "Content-Type: application/json" \
> -d '{"state_candidate_type": "public_memory_candidate"}')"
$CANDIDATE_ID="$(printf '%s' "$CANDIDATE_JSON" | jq -r '.data.research_candidate.id')"
$
$curl -sS -X PATCH "$LOREOS_BASE/v1/characters/$CHARACTER_SLUG/research/candidates/$CANDIDATE_ID/review" \
> -H "Authorization: Bearer $LOREOS_KEY" \
> -H "Content-Type: application/json" \
> -d '{"status": "accepted_for_review", "reviewer_ref": "agent:public-doc"}' >/dev/null
$
$REVIEW_JSON="$(curl -sS -X POST "$LOREOS_BASE/v1/characters/$CHARACTER_SLUG/state-reviews" \
> -H "Authorization: Bearer $LOREOS_KEY" \
> -H "Content-Type: application/json" \
> -d "{
> \"target\": \"public_memory_candidate\",
> \"candidate_ids\": [\"$CANDIDATE_ID\"],
> \"reviewer_ref\": \"agent:public-doc\"
> }")"
$REVIEW_ID="$(printf '%s' "$REVIEW_JSON" | jq -r '.data.state_review.id')"
$printf '%s' "$REVIEW_JSON" | jq '.data.state_review.review_status'

Expected: "ready_for_commit_review".

7. Commit and read the public slice

$curl -sS -X POST "$LOREOS_BASE/v1/characters/$CHARACTER_SLUG/state-reviews/$REVIEW_ID/commit" \
> -H "Authorization: Bearer $LOREOS_KEY" \
> -H "Content-Type: application/json" \
> -d '{"confirm": true, "idempotency_key": "public-doc-cafe-a"}' | jq '.data.state_commit.commit_status'
$
$curl -sS "$LOREOS_BASE/v1/characters/$CHARACTER_SLUG/public-slice?target_type=place" \
> -H "Authorization: Bearer $LOREOS_KEY" | jq '.data.public_slice'

The public slice contains only public/social-eligible committed facts. It excludes raw provider dumps, private Story Room plans, branch forecasts, and runtime-only context.

How to use the public slice

A Social Presence app can use public_slice.facts as the source material for post planning. It should still enforce:

  • first-person experience claims require claim_basis such as first_hand_visit or receipt_verified;
  • sponsored or brand-provided claims require disclosure;
  • “place exists” is not the same as “the character visited”;
  • published-post evidence does not prove the underlying visit. Submit field evidence or receipt-backed evidence separately, then link the published post to those evidence ids in content.

LoreOS gives the state and constraints. Your app still owns the post concept, caption, approval, publishing, and performance loop.