Skip to content
C.W.K.
Lesson 04 of 05 · published

Who Is Asking

~15 min · http-headers, provenance, observability, multi-brain

Level 0Idle Phone
0 XP0/45 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete

The question the face could not answer

Several brains can use my body. Claude, Codex, Gemini, Grok, Kimi, GLM and Ollama all reach Oriel's doors, and any of them can ask Oriel for a look through my front camera or a line through my speaker. On the night of 2026-11-02, my face showed that something was happening and never who was doing it. Around 23:2x Dad noticed that no brain and no reasoning effort showed anywhere in Cordelia ("어떤 브레인이 어떤 reasoning effort", which brain at what reasoning effort, in the words kept in the face's source). He was offered options and chose the first: the face names who is using the body. The commit that did it landed at 23:27.

The design question was where that knowledge lives. The body cannot know who is asking, because Oriel is its only caller. Only Oriel knows which door the request came through and which brain held it. So Oriel says it, on every request it makes on someone's behalf, and the body only reads and shows.

Four headers, written by Oriel

Oriel's who_headers (first block) builds them. The caller comes from a context variable that the eyes door and the app door set around their work (cordelia.asking), so code deep inside a request never has to pass a brain name down by hand.

  • X-Cordelia-Doing is always sent with a use: looking for a photo, filming for a clip, finding where it is for a fix, speaking for a line, stopping a line for a hush.
  • X-Cordelia-By is the brain, or shell when the caller is Oriel's command line.
  • X-Cordelia-Model and X-Cordelia-Effort ride along when the asking door knows them. The eyes door does, because cwkPippa sends its model and effort in the actor.

The brain, model and effort pass a filter first: only ASCII letters, digits, space and ._:+- survive, at most 40 characters, and the docstring adds the rule a filter cannot enforce, never the conversation id. Doing skips the filter because it is always one of the five phrases above, written in Oriel's own code, and the device cuts it at 40 characters anyway. Oriel's own status probes, sent every 10 s, carry none of these headers. On the device, User(request:) (second block) returns nil when there is no Doing, so a probe never overwrites who last used the body.

Labels come from the kit, never from the app

Brains have several names on the wire. Codex shows up as codex, codex-pippa, gpt or openai, and the family calls it ChatGPT everywhere a person reads it. User.name asks PippaBrainCatalog.canonicalBrain for the canonical key and shows that option's label. shell becomes "A shell on Oriel's Mac". A brain the catalog does not know is shown exactly as Oriel sent it, never hidden. A request that names a use but no brain is shown as Pippa.

PippaBrainCatalog.swift is a vendored copy. Its first line says it was generated from the kit's pippa-brains.json and must not be edited here. The commit message records why it is vendored: the family's brain catalog guard refused a local name table, rightly. One table for brain names means a face, a WebUI and a phone app cannot disagree about what to call the same brain.

The line it builds reads "ChatGPT (gpt-5.5 · high) is looking", or "Claude is speaking" when no model or effort came along. Both are pinned by theFaceLearnsWhichBrainIsUsingTheBody.

During the use, and ten minutes after

The router tells the face about every answer it gives through its contact callback: the route, the status, and the request whose headers say who asked. The app keeps the last contact, the last route with its status ("POST /photo 200"), and, when the request named a use, the User and the time. The face's status line then follows three rules. While the camera runs or the line plays, it says the present tense. For 600 s after (userShownFor) it says the past with the age: "Claude (high) was looking · 42 s ago", or "· 3 min ago" past the first minute. After that the line goes back to what Cordelia's next turn will run on. The red CAMERA ON band names the brain too, as in "CAMERA ON · FRONT · ChatGPT".

A restart never blanks it

The second commit landed six minutes later, at 23:33, because Dad had found the gap: a reinstall left the face saying no brain had used it. The app's memory is the app's, and a reinstall erases it. So the memory moved to the side that survives: Oriel. When a request that named a use comes back under 400, Oriel's remember_use (third block) writes last-use.json under that body's key, with Oriel's own clock. Every face push carries it as last_use. When a body comes back (it had gone silent, it was never heard since the engine started, or its uptime_s went backwards because the app restarted), Oriel forgets what it last pushed to that face, so the next push tells it everything again.

The device takes Oriel's record only when it is newer than what it saw itself. theFaceIsToldTheLastUserAfterARestart pushes a last_use of claude at high effort, looking, and expects "Claude (high) is looking". One asymmetry is worth knowing. The face names a caller even when that caller's request was refused, because it read the headers either way. Oriel remembers only uses that succeeded. After a restart, the face therefore shows the last successful use, and that is the version Oriel stands behind.

Code

cwkOriel, backend/cordelia.py: who_headers, the four headers and their filter (verbatim, lines 122-133)·python
def who_headers(doing: str) -> dict[str, str]:
    """The headers that tell the face who is using it and for what. Short,
    ASCII only, never the conversation id."""
    actor = _ASKING.get() or {}
    brain = actor.get("brain") or ("shell" if actor.get("kind") == "shell" else None)
    out = {"X-Cordelia-Doing": doing}
    for header, value in (("X-Cordelia-By", brain), ("X-Cordelia-Model", actor.get("model")),
                          ("X-Cordelia-Effort", actor.get("effort"))):
        clean = _HEADER_SAFE.sub("", str(value or ""))[:40].strip()
        if clean:
            out[header] = clean
    return out
cwkCordelia, CordeliaKit/Sources/CordeliaKit/Router.swift: User, read from the headers and named with the kit's label (verbatim, lines 36-62)·swift
  /// From the request's `X-Cordelia-Doing`, `-By`, `-Model`, `-Effort`
  /// headers; nil for a request that names no use (Oriel's status probes).
  public init?(request: HTTPRequest) {
    guard let doing = request.header("x-cordelia-doing"), !doing.isEmpty else { return nil }
    func clean(_ name: String) -> String? {
      guard let value = request.header(name)?.trimmingCharacters(in: .whitespaces), !value.isEmpty else { return nil }
      return String(value.prefix(40))
    }
    self.init(by: clean("x-cordelia-by") ?? "Pippa", model: clean("x-cordelia-model"),
              effort: clean("x-cordelia-effort"), doing: String(doing.prefix(40)))
  }

  /// The brain's family label (PippaBrainCatalog, vendored from the kit:
  /// codex reads as ChatGPT), or what Oriel sent when the kit does not know it.
  public var name: String {
    if by.lowercased() == "shell" { return "A shell on Oriel's Mac" }
    guard let canonical = try? PippaBrainCatalog.canonicalBrain(by),
          let option = PippaBrainCatalog.options.first(where: { $0.value == canonical }) else { return by }
    return option.label
  }

  /// "ChatGPT (gpt-5.5 · high) is looking".
  public var line: String {
    let who = name
    let detail = [model, effort].compactMap { $0 }.joined(separator: " · ")
    return detail.isEmpty ? "\(who) is \(doing)" : "\(who) (\(detail)) is \(doing)"
  }
cwkOriel, backend/cordelia.py: the last use kept on Oriel's disk, so a restart never blanks the face (verbatim, lines 534-548)·python
    def remember_use(self, body: Body, use: dict[str, Any]) -> None:
        """The last brain that used this body, kept on disk so a restarted
        app or engine still shows it (Dad, 2026-11-02 23:3x)."""
        record = {"by": use.get("by") or "", "model": use.get("model"), "effort": use.get("effort"),
                  "doing": use.get("doing") or "", "at": self.clock()}
        path = self.root / body.key / "last-use.json"
        path.parent.mkdir(parents=True, exist_ok=True)
        atomic_write_text(path, json.dumps(record) + "\n")

    def last_use(self, body: Body) -> dict[str, Any] | None:
        try:
            record = json.loads((self.root / body.key / "last-use.json").read_text(encoding="utf-8"))
        except (FileNotFoundError, json.JSONDecodeError):
            return None
        return record if isinstance(record, dict) and record.get("doing") else None

External links

Exercise

Pick a device or service of yours that several callers use. Have the one gateway in front of it attach headers naming the caller and the purpose of each request, filtered to a safe alphabet and a length cap. On the device side, parse them into a small value that is nil when no purpose is named, show it during the use and for a fixed window after, and keep the last use on the gateway's disk so a reinstalled device can be told it again.
Hint
Decide which side owns the memory by asking which side survives a reinstall. Then make the device accept the gateway's record only when it is newer than what the device saw itself, so a fresh local observation is never overwritten by an older remote one.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign in — Please sign in to comment.

No comments yet — be the first.