feat: the agent's identity and soul are two schema-checked documents - #303
Open
eastriverlee wants to merge 3 commits into
Open
feat: the agent's identity and soul are two schema-checked documents#303eastriverlee wants to merge 3 commits into
eastriverlee wants to merge 3 commits into
Conversation
eastriverlee
force-pushed
the
feat/identity-and-soul-documents
branch
from
September 3, 2026 07:17
3d1209c to
1240ce7
Compare
The runtime read three loose files for who the agent is: a YAML profile the host wrote, plus free-text IDENTITY.md and SOUL.md pasted into the prompt as they were. Nothing said what a field meant, a typo in a key vanished silently, and the same fact could sit in all three. `identity.json` and `soul.json` replace them. Each has a JSON Schema in `internal/persona/schema/` with `additionalProperties: false`, item and length ceilings, and a pinned `schemaVersion`; the package parses, normalizes (trimmed, whitespace-collapsed, deduplicated lists), renders a deterministic instruction block, and writes a canonical form so the host and the runtime agree byte for byte. A document the schema refuses is reported as `application.persona_document_rejected` and left out of the prompt rather than rendered by guesswork. The agent identity the turn briefing introduces itself with comes from the same file. The schema names no product rule such as a fixed name; the host that writes the file owns that. The hand-rolled YAML reader goes with the profile it read. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… document `identity.json` carried one name and an English name, which made every other spelling an alias of lesser standing. It now carries `names`, every one of which is the agent's own; the first is how it introduces itself. The handle leaves the required set because a messenger such as Buzz has none. A third document, `.blueclaw/persona/users/<personID>.json`, says how one person wants to be worked with: what to call them, what to know about them, their preferences, a tone, a language. The launcher reads the requester's document at every launch and appends its rendering to the turn's host instruction, so it reaches the model for that person only. A person ID that is not a plain file name is refused, and a document the schema refuses is logged as `agentruntime.requester_persona_rejected` and left out. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
eastriverlee
force-pushed
the
feat/identity-and-soul-documents
branch
from
September 3, 2026 09:15
33cf94a to
fe5248a
Compare
…s them The person's document sat under the service-owned `.blueclaw/persona/`, where the host had to write it and the service could read it without asking. That is the wrong owner: what a person says about themselves is theirs, and their home is the place the POSIX boundary already protects. It now lives at `private/people/<personID>/.internkim/user.json`. The launcher reads it through the workspace actor as the requester, the same helper path every file tool takes, so a home that is mode 0700 stays closed to the service. `GET` and `PUT /admin/api/persona/user?personID=` read and write it the same way for a host that edits it on the person's behalf; a document the schema refuses answers 400 with the field named and writes nothing. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What to look at
internal/persona/schema/identity.schema.json,soul.schema.json, anduser.schema.json: the three documents' shape. The identity carriesnames[](every one the agent's own, the first is how it introduces itself) and an optionalhandle; a person's document carriescallMe,about,preferences,tone,language.additionalProperties: false, ceilings on every list and string,schemaVersionpinned to 1. These are the contract the host copies; a drift test on the host side compares its copy with these files.internal/persona/persona.go: parse, normalize, canonical form.render.go: the instruction block the prompt gets, and theAgentIdentitythe turn briefing introduces itself with.internal/agentruntime/requester_persona.go: at every launch the requester'sprivate/people/<personID>/.internkim/user.jsonis read as that person through the workspace actor, rendered, and appended to the turn's host instruction, for that person only. The home is mode 0700, so the service never opens it itself; a refused document is logged asagentruntime.requester_persona_rejected.internal/httpserver/persona_handler.go:GETandPUT /admin/api/persona/user?personID=read and write that file the same way for a host that edits it on the person's behalf; a refused document answers 400 naming the field and writes nothing.internal/app/application.go:identity.jsonandsoul.jsonreplaceBOT_PROFILE.yaml,IDENTITY.md, andSOUL.md; a refused document is logged asapplication.persona_document_rejectedand left out.What the model now sees
Instead of a YAML dump and two pasted markdown files, one block per document, for example:
Under two hundred tokens with every field filled; the ceilings keep it there. A person's document adds one more block,
The person asking has told you how they want to work with you:, of at most eight sentences plus a tone and a language line.Evidence
internal/personatests cover normalization, rendering, refusal of unknown fields, wrong versions, over-long values, duplicate list items, and a stable canonical round trip.internal/apptests cover the prompt, the identity, and a refused document staying out with its reason recorded.go test ./...passes.🤖 Generated with Claude Code