-
Notifications
You must be signed in to change notification settings - Fork 59
[agent] Optimize the agent structure by moving the confirmation logic and risk level assessment down to the security service. #1164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
|
@malhotra5 @xingyaoww @enyst hey,PTAL,thanks |
| # Store tools in a dict for easy access | ||
| self._tools = {tool.name: tool for tool in tools} | ||
| # Build the security service based on the state. | ||
| self._security_service = SecurityService(state) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm concerned about including a security service class in the base agent class
some of the security related logic is very specific to the default agent class Agent that we provide
other agent implementations may not require similar logic (extract_security_risk method is the primary example of this)
| if self._security_service.requires_confirmation(action_events): | ||
| state.execution_status = ( | ||
| ConversationExecutionStatus.WAITING_FOR_CONFIRMATION | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original method handled both decision-making and state mutation, but now they're split across classes. This split could lead to inconsistencies if the agent forgets to set the execution status, or if the logic gets out of sync. Any ideas on how we may address this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, the reason for this adjustment is to avoid modifying external resources. Instead, we leave the right to make modifications to the caller, preserving the read-only nature of this method.
If needed, I think we can implement a method in DefaultSecurityService to handle the state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think splitting the security context from the agent is the right direction! However, the security context can affect the agent's control loop so I think we want an interface that
- is flexible enough so different agents can implement their own requirements (based on the analyzer outputs, security policy, state, etc)
- returns a result object that includes both the decision and the required state changes, so the agent can coordinate reliably based on the results
Signed-off-by: CLFutureX <[email protected]>
Thanks for your suggestions! Based on your input, I've made the following adjustments: |
Signed-off-by: CLFutureX <[email protected]>
malhotra5
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments, I think we're getting closer but would like to be a bit more intentional regarding the interfaces and how we enforce separation of concerns between the agent and the security related logic
| @@ -0,0 +1,110 @@ | |||
| from abc import ABC, abstractmethod | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SecurityService (interface)
├── SecurityServiceBase (base implementation)
└── DefaultSecurityService (concrete implementation)
We seem to have multiple layers for the interface, could we reduce them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, adjustments done!
|
|
||
|
|
||
| class DefaultSecurityService(SecurityServiceBase): | ||
| def __init__(self, state: "ConversationState"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| def __init__(self, state: "ConversationState"): | |
| def __init__( | |
| self, | |
| security_analyzer: SecurityAnalyzerBase | None, | |
| confirmation_policy: ConfirmationPolicy | |
| ): |
Let's de-couple the security service as much as possible. Ideally we don't pass the entire state object. The security service should return a typed object which includes the final decision (whether the control loop should pause, reject, etc) and the agent can use to modify its state properly
Also I'm considering returning a typed object with the final security assessment, so that the agent can interpret it easily and we can standardize the assessment requirements. for example, the method requires_confirmation returns the following typed object
class SecurityAssessment:
requires_confirmation: bool
overall_risk_assessment: SecurityRisk
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's de-couple the security service as much as possible. Ideally we don't pass the entire state object. The security service should return a typed object which includes the final decision (whether the control loop should pause, reject, etc) and the agent can use to modify its state properly
Also I'm considering returning a typed object with the final security assessment, so that the agent can interpret it easily and we can standardize the assessment requirements. for example, the method
requires_confirmationreturns the following typed objectclass SecurityAssessment: requires_confirmation: bool overall_risk_assessment: SecurityRisk
For now, I still choose to keep ConversationState, since both confirmation_policy and security_analyzer can be updated during the conversation.
| ): | ||
| self._state = state | ||
|
|
||
| def requires_confirmation( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| def requires_confirmation( | |
| def assess_actions( |
I think maybe we should make this a more generic name. Possibly even pass the entire event history here as well since we may develop other security policies based on prior events
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, Adjusted to access_confirm.
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Signed-off-by: CLFutureX <[email protected]>
Hey, Thanks for your suggestions! PTAL, thanks |
|
Thanks for the changes!
I'd still prefer if this wasn't the case. The reason being that the control loop is stopped by the agent and reflected by modifying state parameters. So we should avoid manipulating the state object outside of the agent. While that's not the case today, passing the entire state object can imply that its allowed. The separation I'd like is
I think if we pass a reference from the state object |
Motivation:
Right now, the agent has extra logic mixed in. The agent should only handle coordination and scheduling—extra logic should go to the right areas it belongs to.
Modification:
Move the current requires_confirmation and extract_security_risk logic down to the security area, and let the security service manage them.