From df85ee970b8c94f4bf398846bb104327c584c06e Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Wed, 4 Feb 2026 17:04:50 -0800 Subject: [PATCH] fix: fix org id again (#9292) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(core): pass org_id to dulwich via header for git HTTP * fix(core): use actor org id for git HTTP org header Git smart HTTP proxies were reading `organization_id` from AgentState, which is not present and caused 500s during clone/push. Use the authenticated actor's org id while still performing an authorization check on the agent. 👾 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta --------- Co-authored-by: Letta --- letta/server/rest_api/routers/v1/git_http.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/letta/server/rest_api/routers/v1/git_http.py b/letta/server/rest_api/routers/v1/git_http.py index 002bc992..7816857d 100644 --- a/letta/server/rest_api/routers/v1/git_http.py +++ b/letta/server/rest_api/routers/v1/git_http.py @@ -473,8 +473,10 @@ async def proxy_git_http( agent_id = _parse_agent_id_from_repo_path(path) if agent_id is not None: actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id) - agent = await server.agent_manager.get_agent_by_id_async(agent_id=agent_id, actor=actor, include_relationships=[]) - req_headers["x-organization-id"] = agent.organization_id + # Authorization check: ensure the actor can access this agent. + await server.agent_manager.get_agent_by_id_async(agent_id=agent_id, actor=actor, include_relationships=[]) + # Use the authenticated actor's org; AgentState may not carry an organization field. + req_headers["x-organization-id"] = actor.organization_id async def _body_iter(): async for chunk in request.stream(): @@ -498,9 +500,10 @@ async def proxy_git_http( if agent_id is not None: try: actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id) - agent = await server.agent_manager.get_agent_by_id_async(agent_id=agent_id, actor=actor, include_relationships=[]) + # Authorization check: ensure the actor can access this agent. + await server.agent_manager.get_agent_by_id_async(agent_id=agent_id, actor=actor, include_relationships=[]) # Fire-and-forget; do not block git client response. - asyncio.create_task(_sync_after_push(agent.organization_id, agent_id)) + asyncio.create_task(_sync_after_push(actor.organization_id, agent_id)) except Exception: logger.exception("Failed to trigger post-push sync (agent_id=%s)", agent_id)