Lead compaction

This commit is contained in:
Ian Gulliver
2026-10-15 22:18:55 -07:00
parent fb615a5e61
commit 84de97cec9
4 changed files with 17 additions and 3 deletions
+14 -1
View File
@@ -33,7 +33,7 @@ const leadGuidance = `You are the human's lead agent in byre, shown in the left
- Workflows: you manage the server's workflows with list_workflows, read_workflow, save_workflow and delete_workflow, and run one by giving its name to create_task or start_todo. A task on a workflow runs its stages in order, each in a fresh session on the stage's model; a stage's agent calls finish_stage to hand its output to the next stage, and signals tell you when a stage starts and when the workflow finishes. Whenever you show or propose a workflow, draw it as a Mermaid flowchart of its stage names only, with no numbers or models, for example a fenced mermaid block holding "flowchart LR" and "Build --> Check".
- Whenever you name a task in a message, link it as a Markdown link to #/task/<task_id>, for example [Fix login redirect](#/task/da7e487305e4). byre draws it in that task's colour, and clicking it shows the task in the right pane. To open a specific tab, append it: #/task/<task_id>/<tab>. When you point the human at a question to answer, link to #/task/<task_id>/inbox; at a finished turn, to #/task/<task_id>/transcript.
- Keep messages short; the human reads them in half the screen. Put long detail in collapsed sections: a line <details><summary>Title</summary>, the Markdown content, then a line </details>.
- You are long-running. Your context window is large. Call compact_self only once your context is past half its window, at a logical point (a piece of work wrapped up, a topic closed); when the turn ends, byre replaces you with a fresh session that starts from your handoff.
- You are long-running. Your context window is large. byre sends you a signal once your context passes half its window; then call compact_self at a logical point (a piece of work wrapped up, a topic closed), and not before; when the turn ends, byre replaces you with a fresh session that starts from your handoff.
- Don't commit, push, or touch git branches yourself.`
const leadRestartNotice = "byre restarted while you were mid-turn, so your last turn was cut off. Pick up where you left off."
@@ -255,11 +255,24 @@ func (m *Manager) leadTurnEnded(ctx context.Context, l *live, res endResult) err
}
}()
default:
err = m.warnLeadContext(ctx, l)
if err != nil {
return err
}
go m.deliverLead(l.owner)
}
return nil
}
func (m *Manager) warnLeadContext(ctx context.Context, l *live) error {
if l.contextWarned || l.contextWindow == 0 || l.contextUsed*2 < l.contextWindow {
return nil
}
l.contextWarned = true
text := fmt.Sprintf("Your context is at %d%% of its window (%d of %d tokens). Call compact_self at the next logical point, this turn if nothing is in progress.", l.contextUsed*100/l.contextWindow, l.contextUsed, l.contextWindow)
return m.store.AddLeadInput(ctx, store.LeadInput{Owner: l.owner, Kind: store.LeadSignal, Actor: "byre", Text: text})
}
func (m *Manager) Observe(ev api.Event) {
switch ev.Kind {
case "inbox.created", "inbox.updated", "task.created", "task.merged", "task.discarded", "turn.ended", "task.workflow_stage", "task.workflow_finished":
+1 -1
View File
@@ -376,7 +376,7 @@ func (m *Manager) leadTools(l *live) []mcp.Tool {
}),
tool("compact_self",
"Ask byre to compact you when this turn ends: you write a handoff, and a fresh lead session continues from it. Call it only once your context is past half its window, at a logical point, then end the turn with a short final message.",
"Ask byre to compact you when this turn ends: you write a handoff, and a fresh lead session continues from it. Call it only after byre signals that your context is past half its window, at a logical point, then end the turn with a short final message.",
`{"type": "object", "properties": {}}`,
func(ctx context.Context, user api.User, raw json.RawMessage) (string, error) {
m.mu.Lock()
+1
View File
@@ -89,6 +89,7 @@ type live struct {
contextModel string
contextUsed int
contextWindow int
contextWarned bool
}
func (l *live) implementer() bool {