SBIR awards agent#100
Conversation
Update version and appVersion for deployment.
There was a problem hiding this comment.
Pull request overview
Adds additional “custom agent” wiring for a demo deployment, primarily by introducing an SBIR awards agent (and also including an Austin permits agent copy), plus some deployment and frontend-generated-file updates.
Changes:
- Hard-codes Helm chart
version/appVersionfor a dev deployment. - Adds two backend custom agents (
sbir_award_agentandaustin_permit_agent) that can query Postgres and emit chart/map UI events. - Updates generated TanStack Router route typings and expands
.gitignorefor local config artifacts.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| helm/nebari-chat/Chart.yaml | Overrides chart/app versions with a dev value (previously CD-controlled). |
| frontend/src/routeTree.gen.ts | Regenerates TanStack Router route type mappings (including fullPath updates). |
| backend/src/ravnar_nebari_chat/sbir_award_agent.py | Adds SBIR awards agent with schema/query/chart/map tools. |
| backend/src/ravnar_nebari_chat/austin_permit_agent.py | Adds Austin permits agent with schema/query/chart/map tools. |
| .gitignore | Ignores local backend config files and .ravnar_local. |
Comments suppressed due to low confidence (3)
backend/src/ravnar_nebari_chat/austin_permit_agent.py:90
execute_queryruns whatever SQL the model returns. Relying solely on a “read-only mount” is brittle if credentials/DB config ever permit writes, and it also allows potentially dangerous statements (DDL, COPY, etc.) or very expensive queries. Please enforce read-only at the connection/session level (e.g.,default_transaction_read_only=on,statement_timeout) and/or validate that the query is a safe read-only statement before executing.
async def execute_query(query: str) -> list[tuple]:
"""Execute a query against the Austin Permits database.
The query should not attempt to modify the db in any way.
The db is mounted as readonly, so queries that attempt to modify it will fail.
This tool takes a single argument, which is the SQL to execute
against the db. The db is Postgres, so use Postgres-compatible
SQL syntax.
"""
async with await db_conn() as conn, conn.cursor() as cur:
await cur.execute(query)
return list(await cur.fetchall())
backend/src/ravnar_nebari_chat/sbir_award_agent.py:177
- The map popup is explicitly an arbitrary HTML string (
feature.properties.popup), and the frontend binds it directly as HTML via Leaflet. If any values interpolated into the popup come from the database (or user input), this can create an XSS vector. Consider switching the tool contract to structured popup fields rendered safely on the frontend, or ensure popup content is HTML-escaped/sanitized before it reaches Leaflet.
To add a popup, create a 'popup' key in the properties of the
feature. Use an HTML string to define the contents of the popup.
Any other key in the properties of a feature besides 'popup' will
be ignored.
backend/src/ravnar_nebari_chat/austin_permit_agent.py:133
create_maprequires popup content as an HTML string, and the frontend binds that string directly as HTML in Leaflet. If popup content includes any untrusted values (e.g., from the permits DB), this can become an XSS vector. Consider using structured popup data rendered safely on the frontend, or ensure popup content is escaped/sanitized before rendering.
Use the 'features' key to define an additional GeoJSON feature
collection, such as markers with popup metadata, to add to the map.
This dictionary must be a valid GeoJSON feature collection.
To add a popup, create a 'popup' key in the properties of the feature.
Use an HTML string to define the contents of the popup. Any other key
in the properties of a feature besides 'popup' will be ignored.
If a link to the permit is available, include it in any popup.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Both the Austion Permits and SBIR Awards agent used the exactly same tools with minimal configuration. Thus, I factored out the tools into this common package that can be used by both.
There was a problem hiding this comment.
The old visualization tools just described the tool schema as part of the docstring. That is way less strict and interpretable by the agent. Instead, I've defined proper input models for the tools, which are automatically picked up by pydantic_ai.
Reference Issues or PRs
Just copying the pattern in #97 verbatim to build a second agent for a demo
What does this implement/fix?
Put a
xin the boxes that applyTesting
Documentation
Access-centered content checklist
Text styling
H1or#in markdown).Non-text content
Any other comments?