Skip to content

Add frames agent#163

Closed
jbouder wants to merge 4 commits into
mainfrom
frames-chat
Closed

Add frames agent#163
jbouder wants to merge 4 commits into
mainfrom
frames-chat

Conversation

@jbouder

@jbouder jbouder commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Reference Issues or PRs

What does this implement/fix?

Put a x in the boxes that apply

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds a feature)
  • Breaking change (fix or feature that would cause existing features not to work as expected)
  • Documentation Update
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no API changes)
  • Build related changes
  • Other (please describe):

Testing

  • Did you test the pull request locally?
  • Did you add new tests?

Documentation

Access-centered content checklist

Text styling

  • The content is written with plain language (where relevant).
  • If there are headers, they use the proper header tags (with only one level-one header: H1 or # in markdown).
  • All links describe where they link to (for example, check the Nebari website).
  • This content adheres to the Nebari style guides.

Non-text content

  • All content is represented as text (for example, images need alt text, and videos need captions or descriptive transcripts).
  • If there are emojis, there are not more than three in a row.
  • Don't use flashing GIFs or videos.
  • If the content were to be read as plain text, it still makes sense, and no information is missing.

Any other comments?

jbouder and others added 2 commits July 2, 2026 11:54
Replace the static mcp_token with per-user auth: the authenticator now
keeps the raw bearer token on User.data, and the frames agent forwards
it on every MCP request via an httpx auth hook fed by a context variable
seeded at the start of each run. The frames endpoint validates the token
as long as its aud claim includes the MCP resource identifier, which an
audience mapper on the chat Keycloak client provides.

Capabilities are now declared statically instead of extracted at boot:
extraction opens an MCP connection outside any run, where no user token
exists, and the now-authenticated endpoint would 401 and fail startup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread backend/src/ravnar_nebari_chat/_authenticators.py Outdated
pmeier
pmeier previously requested changes Jul 3, 2026

@pmeier pmeier left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With #164 merged, all the MCP handling in this PR is superseded. The only thing left is setting the agent name and system prompt. Both can be set through the agent constructor and thus directly through the ravnar config. Meaning, unless we need anything beyond the MCP connection and the system prompt, this PR does not add anything.

@pmeier pmeier dismissed their stale review July 6, 2026 15:17

resolved after merge

@pmeier

pmeier commented Jul 6, 2026

Copy link
Copy Markdown
Member

@jbouder I cleaned up the branch after #164 was merged. As of now a valid config for this branch could look like

agents:
  static:
    frames:
      cls_or_fn: ravnar_nebari_chat.make_frames_agent
      params:
        agent:
          cls_or_fn: pydantic_ai.Agent
          params:
            model:
              cls_or_fn: pydantic_ai.models.google.GoogleModel
              params:
                model_name: gemini-flash-latest
                provider:
                  cls_or_fn: pydantic_ai.providers.google.GoogleProvider
                  params:
                    api_key: '{{ GOOGLE_API_KEY }}'
        mcp_url: "http://my-mcp-server"
        oidc_issuer: "http://keycloak-keycloakx-http.keycloak.svc.cluster.local:8080/realms/nebari"
        client_id: '{{ CLIENT_SECRET }}'
        client_secret: '{{ CLIENT_SECRET }}'

However, as explained here likely this branch is not needed. Here is how to get the exact same result on top of 0.0.14

agents:
  static:
    frames:
      cls_or_fn: ravnar.agents.PydanticAiAgentWrapper
      params:
        agent:
          cls_or_fn: pydantic_ai.Agent
          params:
            model:
              cls_or_fn: pydantic_ai.models.google.GoogleModel
              params:
                model_name: gemini-flash-latest
                provider:
                  cls_or_fn: pydantic_ai.providers.google.GoogleProvider
                  params:
                    api_key: '{{ GOOGLE_API_KEY }}'
            name: Nebari Frames Agent
            system_prompt: |
              You are an agent that answers the user's questions using the
              nebari-frames tools. Those tools are provided over MCP; inspect the
              tools available to you and call them to fetch data and perform
              actions rather than guessing.
  
              Prefer calling a tool over answering from memory whenever the answer
              depends on live data. When a tool fails or returns nothing useful,
              explain what you tried instead of inventing a result.
            toolsets:
              - cls_or_fn: ravnar_nebari_mcp.ImpersonatingMCPToolset
                params:
                  mcp_toolset_factory:
                    cls_or_fn: ravnar_nebari_mcp.bearer_token_mcp_toolset_factory
                    params:
                      url: http://my-mcp-server
                  impersonator:
                    cls_or_fn: ravnar_nebari_mcp.OIDCImpersonator
                    params:
                      issuer: http://keycloak-keycloakx-http.keycloak.svc.cluster.local:8080/realms/nebari
                      client_id: '{{ CLIENT_ID }}'
                      client_secret: '{{ IMPERSONATOR_CLIENT_SECRET }}'

@jbouder

jbouder commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

It works! Closing this PR.

@jbouder jbouder closed this Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants