Skip to content

[PLAT-416] ensure bounded time range for mv query tool call#8887

Merged
begelundmuller merged 9 commits intomainfrom
defensive_tool_call
Feb 27, 2026
Merged

[PLAT-416] ensure bounded time range for mv query tool call#8887
begelundmuller merged 9 commits intomainfrom
defensive_tool_call

Conversation

@pjain1
Copy link
Member

@pjain1 pjain1 commented Feb 19, 2026

To prevent LLMs to run unbounded queries

Checklist:

  • Covered by tests
  • Ran it and it works as intended
  • Reviewed the diff before requesting a review
  • Checked for unhandled edge cases
  • Linked the issues it closes
  • Checked if the docs need to be updated. If so, create a separate Linear DOCS issue
  • Intend to cherry-pick into the release branch
  • I'm proud of this work!

Copy link
Contributor

@begelundmuller begelundmuller left a comment

Choose a reason for hiding this comment

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

Two thoughts:

  1. It might be nice to be able to disable this for projects that run into problems. So maybe add it as a rill.ai.name instance-level flag? So it can be overridden at runtime if someone has problems.
  2. I'm wondering if the AI will just get the full time range using the summary tool call and then use that, which will have similar bad performance. Do you think it would make sense to instead support a bounding by a number of days, e.g. rill.ai.max_time_range_days? So e.g. users with large clusters could bound AI queries to max 30 days of data.

@pjain1 pjain1 changed the title ensure bounded time range for mv query tool call [PLAT-416] ensure bounded time range for mv query tool call Feb 20, 2026
@pjain1
Copy link
Member Author

pjain1 commented Feb 21, 2026

IMO we should definitely ensure that a valid time range is set, absence of it just means LLM is not able to some how use it, may be this can be also behind a flag and default is ensure time range, what do you think? I agree we can have rill.ai.max_time_range_days and have a default of 0 means no restriction as some projects having less data might want to actually use full time range and in those cases LLM can specify the full time range retrieved from summary tool call.

return nil
}

if qry.TimeRange.IsZero() {
Copy link
Member Author

Choose a reason for hiding this comment

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

put this behind feature flag?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm okay with keeping it required for AI initially – but try running the evals in analyst_agent_test.go and check they still pass

Copy link
Member Author

@pjain1 pjain1 Feb 24, 2026

Choose a reason for hiding this comment

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

They pass (has to disable enforcing of time range for tests directly doing query_metrics_view tool call) except from CanvasContext test which fails here and I think its a genuine failure as I am not sure why app_or_site = 'App' this filter would be present in where clause.

Copy link
Contributor

Choose a reason for hiding this comment

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

Then it's flaky. The filter is because the contextual canvas component has it:

dimension_filters: app_or_site IN ('App')

- Prefer using absolute 'start' and 'end' times in 'time_range' and 'comparison_time_range' if available.
Otherwise, use 'expression' for relative time ranges, when specifying 'expression' make sure no other time range fields should be set as its not supported.
- Prefer using absolute 'start' and 'end' time range parameters in 'time_range' and 'comparison_time_range' if available.
Otherwise, use 'time_range.expression' for relative time ranges, when specifying 'time_range.expression' make sure no other time range fields other than 'time_range.time_dimension' is set as its not supported.
Copy link
Contributor

Choose a reason for hiding this comment

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

The problem with this is that there is also comparison_time_range.expression (and expressions are usually most useful for comparisons)

Comment on lines 31 to 32

QueryLimit *QueryLimits `json:"-" mapstructure:"query_limits"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason not to expose this?

Suggested change
QueryLimit *QueryLimits `json:"-" mapstructure:"query_limits"`
QueryLimit *QueryLimits `json:"limits,omitempty" mapstructure:"query_limits"`

Copy link
Member Author

@pjain1 pjain1 Feb 26, 2026

Choose a reason for hiding this comment

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

Yes, this will be used only during AI tool calls and resolvers use mapstructure to decode the args, also query limits are not exposed through any proto requests so didn't felt need to expose it.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should just expose it. I'm not sure, but I think we may have some places that use JSON instead of mapstructure for serialization/deserialization, or if not, we might add that in the future. So since it would not be harmful to expose, I think it might just be simpler/safer.

Copy link
Member Author

@pjain1 pjain1 Feb 26, 2026

Choose a reason for hiding this comment

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

ok why use limits as key instead of query_limits, seems confusing with already present limit key.

Copy link
Member Author

Choose a reason for hiding this comment

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

added json tags

Copy link
Contributor

Choose a reason for hiding this comment

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

Was just typing quickly, query_limits also seems fine by me

Comment on lines 65 to 69
// QueryLimits represents limits that should be applied to a query, such as requiring a time range or limiting the maximum time range for interactive queries. These are not part of the Query json itself because they are not intrinsic to the query, but rather are constraints that may be applied to the query before execution.
type QueryLimits struct {
RequireTimeRange bool `json:"-" mapstructure:"require_time_range"`
MaxTimeRangeDays int `json:"-" mapstructure:"max_time_range_days"`
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question about exposing it.

Is it a problem to consider it as part of the query? From the metricsview package perspective, I guess it is part of the query? It is only from the API/tool perspective that it may overwrite it (i.e. not allow the user to set it).

Copy link
Contributor

@begelundmuller begelundmuller left a comment

Choose a reason for hiding this comment

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

LGTM!

@begelundmuller begelundmuller merged commit 5f88a72 into main Feb 27, 2026
18 of 19 checks passed
@begelundmuller begelundmuller deleted the defensive_tool_call branch February 27, 2026 16:16
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