diff --git a/agent.go b/agent.go index 144e9c2..7c84015 100644 --- a/agent.go +++ b/agent.go @@ -76,8 +76,13 @@ type AgentState struct { Fragment *Fragment Error error Cancel context.CancelFunc - done chan struct{} - inject chan openai.ChatCompletionMessage + // Background reports whether the agent was spawned to run in the background + // (spawn_agent background=true) rather than in the foreground. Embedders use + // it to tell unattended background work apart from a foreground sub-agent + // whose result is consumed inline by the spawn call. + Background bool + done chan struct{} + inject chan openai.ChatCompletionMessage // detach, when non-nil, lets an embedder promote a running foreground // agent to the background: a non-blocking send here unblocks the // spawn_agent call so it returns the agent ID while the goroutine keeps @@ -405,13 +410,14 @@ func (r *spawnAgentRunner) Run(args SpawnAgentArgs) (string, any, error) { // Background: launch goroutine, return ID immediately. agent := &AgentState{ - ID: agentID, - Task: args.Task, - Type: args.AgentType, - Status: AgentStatusRunning, - Cancel: cancel, - done: make(chan struct{}), - inject: make(chan openai.ChatCompletionMessage, 8), + ID: agentID, + Task: args.Task, + Type: args.AgentType, + Status: AgentStatusRunning, + Cancel: cancel, + Background: true, + done: make(chan struct{}), + inject: make(chan openai.ChatCompletionMessage, 8), } r.manager.Register(agent) if r.agentSpawnCallback != nil { diff --git a/agent_background_test.go b/agent_background_test.go new file mode 100644 index 0000000..752727c --- /dev/null +++ b/agent_background_test.go @@ -0,0 +1,28 @@ +package cogito + +import ( + "context" + "testing" +) + +// TestBackgroundSpawnSetsBackgroundFlag verifies that a background spawn marks +// the AgentState so embedders can tell it apart from a foreground sub-agent. +func TestBackgroundSpawnSetsBackgroundFlag(t *testing.T) { + m := NewAgentManager() + llm := newBlockingLLM(make(chan struct{})) // blocks; background spawn returns immediately + runner := &spawnAgentRunner{llm: llm, manager: m, ctx: context.Background()} + + _, idAny, err := runner.Run(SpawnAgentArgs{Task: "bg job", Background: true}) + if err != nil { + t.Fatalf("background Run: %v", err) + } + id, _ := idAny.(string) + a, ok := m.Get(id) + if !ok { + t.Fatal("background agent should be registered") + } + if !a.Background { + t.Fatal("a background spawn should set AgentState.Background = true") + } + a.Cancel() // unblock the goroutine so the test cleans up +}