aaif-goose/goose · error

AGENT_SESSION_ID not set. Initialize terminal integration w

Error message

AGENT_SESSION_ID not set.

Initialize terminal integration with `goose term init <shell>` in your shell profile, then restart or reload that shell.

What it means

`goose term run` forwards a prompt to the agent session attached to the current terminal, identified by the AGENT_SESSION_ID env var set up by `goose term init <shell>`. Without the var there is no session to update (it also sets working_dir on that session), so the handler fails before touching the session manager.

Source

Thrown at crates/goose-cli/src/commands/term.rs:268

fn shell_history_text(newest_first_tail: &[&Message]) -> Option<String> {
    let history: Vec<String> = newest_first_tail
        .iter()
        .filter(|m| !m.is_turn_context())
        .rev()
        .map(|m| m.as_concat_text())
        .collect();
    if history.is_empty() {
        None
    } else {
        Some(history.join("\n"))
    }
}

pub async fn handle_term_run(prompt: Vec<String>) -> Result<()> {
    let prompt = prompt.join(" ");
    let session_id = std::env::var("AGENT_SESSION_ID").map_err(|_| {
        anyhow!(
            "AGENT_SESSION_ID not set.\n\n\
             Initialize terminal integration with `goose term init <shell>` in your shell profile, \
             then restart or reload that shell."
        )
    })?;

    let working_dir = std::env::current_dir()?;
    let session_manager = SessionManager::instance();

    session_manager
        .update(&session_id)
        .working_dir(working_dir)
        .apply()
        .await?;

    let session = session_manager.get_session(&session_id, true).await?;
    let user_messages_after_last_assistant: Vec<&Message> =
        if let Some(conv) = &session.conversation {

View on GitHub (pinned to 3810898a74)

Solutions

  1. Initialize the integration (`goose term init zsh` etc.) in your profile and restart/reload the shell
  2. Confirm `echo $AGENT_SESSION_ID` is set before calling term run
  3. In non-interactive contexts use `goose run`/`goose session` commands that do not depend on the env var

Example fix

# before
goose term run 'fix the failing test'
# after
goose term init zsh > ~/.config/goose/term.zsh && echo 'source ~/.config/goose/term.zsh' >> ~/.zshrc && exec zsh
goose term run 'fix the failing test'
Defensive patterns

Strategy: validation

Validate before calling

let Some(session_id) = std::env::var("AGENT_SESSION_ID").ok().filter(|v| !v.is_empty()) else {
    eprintln!("terminal integration not initialized; run `goose term init <shell>`");
    return Ok(());
};

Type guard

fn term_integration_active() -> bool {
    std::env::var("AGENT_SESSION_ID").map(|v| !v.is_empty()).unwrap_or(false)
}

Try / catch

match handle_term_run(prompt).await {
    Err(e) if e.to_string().contains("AGENT_SESSION_ID not set") => {
        // fall back to a non-integrated entry point, e.g. goose run
        run_via_goose_run(&prompt).await
    }
    other => other,
}

Prevention

When it happens

Trigger: Running `goose term run <prompt>` in a non-integrated shell; after `env -i`; in a new terminal tab that did not source the profile containing the init script.

Common situations: Same as term log: shell profile not reloaded, SSH/cron contexts, or the integration script removed from rc files.

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/d5152964edb8cc45. Report an issue: GitHub.