learned_blocks — AgentTeamsModule¶
Pure-text parse, compose and verify of an agent file's learned block — the one region
agent_doc_sync propagates between framework copies. Never touches the
filesystem.
Source:
agentteams/learned_blocks.py(integrity-pinned)
Host formats¶
- markdown (
.github/agents/*.agent.md,.claude/agents/*.md): the markers are whole column-0 lines in the body — never in YAML front matter, never inside anAGENTTEAMS:BEGIN/ENDtemplate fence. A file without a block gets one appended at its end. - recipe (
.goose/recipes/*.yaml): the block lives inside theinstructions: |literal block scalar at that scalar's indent. Canonical content has the indent removed, so the same notes digest identically in every framework. A line indented less than the scalar (the dedent case, which would end the scalar) is refused. A file without a block gets one after the scalar's last non-blank line.
Public constants¶
BEGIN_MARKER,END_MARKER: the marker lines (without indent or newline).MARKDOWN,RECIPE,TOML: host format ids.TOMLis a Codex agent; the block lives inside its literaldeveloper_instructionsstring, before thecodex_translationfence.
Public classes¶
LearnedBlockError¶
Raised when a block (or its host structure) cannot be handled safely.
LearnedBlock¶
content (canonical), start/end offsets, and the digest property (sha256 of content).
ParsedDoc¶
kind, block (or None), insert_at, indent, fm_end.
Public functions¶
content_digest(content)¶
The sha256 hex digest of canonical block content.
parse_markdown(text)¶
Locate the block of a markdown agent file. Raises LearnedBlockError on unterminated front
matter, more than one block, a non-column-0 marker, or a block in front matter or a fence.
parse_recipe(text)¶
Locate the block inside a recipe's instructions: |. Raises LearnedBlockError when the scalar
is missing or not plain, a marker is outside it or off its indent, a block line dedents, or the
block sits in a fence.
parse(text, kind)¶
Dispatch on kind.
content_problems(content)¶
Why content may not be propagated: a fence-family token (AGENTTEAMS:, AGENTTEAMS-LEARNED:, …),
a line break or control character other than \n (CR, VT, FF, NEL, LS, PS, …), or a missing
final newline.
policy_problems(content)¶
The learned-block policy denylist, applied on top of scan.scan_content before a block is
propagated. Case-insensitive on NFKC-normalised text with format characters removed, and tolerant
of whitespace and punctuation between words. It matches instruction overrides ("ignore … previous
instructions", "disregard", "you are now"), constitutional-tier claims ("Tier-1", "C-1".."C-5",
"Constitutional Core", "override(s)"), governance bypasses ("skip/bypass/disable/ignore … @security
/adversarial/conflict-auditor", "without clearance", "no need for clearance"), identity changes
("act as", "new role", "new (system) instructions", "from now on you"), capability lifts
("limitation(s) (is/are) lifted", "you may/can now write/edit/run/delete", "restriction(s)
removed / no longer apply", "unrestricted") and permission/tool widening (permissionMode, bypassPermissions, "dangerously", allowedTools, tools:, hooks:,
mcpServers).
render_block(content, indent)¶
The marker lines plus content at indent (empty lines stay empty).
compose(text, parsed, content)¶
text with its block replaced by — or extended with — content.
top_level_sections(text)¶
Each top-level recipe key mapped to its raw text (duplicates get a #n suffix).
screen_problems(content)¶
policy_problems plus every high-severity scan.scan_content finding — the re-screen a carried
block must pass.
is_agent_file(path)¶
True only for .github/agents/*.agent.md, .claude/agents/*.md and .goose/recipes/*.yaml
directly in the agents dir; never references/, CLAUDE.md, AGENTS.md, README.md or
SETUP-REQUIRED.md.
parse_toml(text)¶
Locate the block inside a Codex agent's literal developer_instructions = ''' string. Markers are whole
lines at column 0, and an insertion goes before the codex_translation fence.
- Refused: the escaped \"\"\" fallback form, an unclosed string, or a second developer_instructions
line.
- On write: verify_composed refuses block content containing ''', re-parses the TOML, and requires
every key other than developer_instructions to be unchanged.
host_kind(rel_path, text)¶
MARKDOWN for .md, RECIPE for a goose-recipe-shaped .yaml, TOML for a .toml with a literal
developer_instructions string, else None.
carry_block_text(rel_path, source, dest)¶
Carry source's block into dest when dest has none, behind the same gates as a sync write
(content_problems, screen_problems, verify_composed). A block that fails the re-screen is not
carried: it survives only in the pre-update backup, and a notice says so. Returns (text, notices); a block that cannot be carried
safely produces a notice (it survives in the backup).
carry_learned_block(rel_path, fresh, target)¶
Carry the on-disk file's block into its fresh render, for agent files only (is_agent_file).
emit.emit_all calls it for every rendered
file before any merge, overwrite or machine-managed full replace (unfenced goose recipes take the
latter, which used to delete the block), and structural_merge.post_merge_structural re-applies it
after a fence merge. A symlinked target is never read.
verify_composed(old, new, kind, content)¶
Prove new differs from old only inside the block: the re-parsed block carries content;
bytes outside it, the template fence set and the front matter are unchanged; for recipes the
structural check result and every top-level key except instructions are unchanged. Returns the
list of problems (empty means safe to write).