AI Agents Operations and Control Planes
Master management, monitoring, and security of intelligent autonomous agents
Learning Outcomes
- Understand AI agent architecture and core control concepts
- Design and implement complex Control Planes
- Manage monitoring, logging, and observability in production
- Apply safety mechanisms, permissions, and constraints to intelligent agents
Fundamentals of AI Agents and Control
180 minutes
AI agents are autonomous systems capable of perceiving their environment, making decisions, and taking actions to achieve specific goals. Unlike traditional software that requires explicit instructions for every scenario, agents learn from interactions and adapt their behavior. Understanding the foundational architecture of these systems is critical for anyone responsible for managing them in production environments.
The core architecture of an AI agent consists of perception modules that gather data from the environment, a decision-making engine powered by machine learning models, memory systems that store context and experiences, and action execution modules that interact with external systems. These components work together in a feedback loop, constantly updating the agent's understanding and refining its behavior. Control planes sit between the operator and the agent, enforcing policies, monitoring behavior, and ensuring alignment with organizational objectives.
Governance refers to the framework of rules, policies, and procedures that guide agent behavior. Policy defines specific constraints and permitted actions. Enforcement is the technical mechanism ensuring agents comply with policies. We distinguish between different types of control: preventive controls that stop prohibited actions before they occur, detective controls that identify non-compliant behavior after it happens, and corrective controls that automatically remediate violations. Understanding these distinctions helps in designing robust control systems.
Centralized control systems place all decision-making authority with a single control plane, offering simplicity and consistency but creating potential bottlenecks. Decentralized systems distribute control across multiple nodes, improving resilience and scalability but introducing coordination complexity. Hybrid approaches combine both, using a central policy store with distributed enforcement points. The choice depends on your operational requirements, scale, and risk tolerance.
Key Concepts in This Module
Perceive → Reason → Act → Observe feedback → Update model
Policy Store, Enforcement Engine, Monitoring System, Decision Log
Preventive, Detective, Corrective, and Compensating controls
Code Example: Agent State Representation
Effective agent management requires balancing three dimensions: autonomy (how much can the agent decide), observability (can we see what it's doing), and safety (can we prevent harm). Most failures occur when one dimension is neglected.
Comparison of Control Architectures
| Architecture | Latency | Scalability | Complexity |
|---|---|---|---|
| Centralized | High (single point) | Limited | Low |
| Decentralized | Low (distributed) | Excellent | High |
| Hybrid | Medium (balanced) | Good | Medium |
Designing Control Planes
240 minutes
A Control Plane is the orchestration layer that manages agent lifecycle, enforces policies, makes high-level decisions, and coordinates with other system components. It consists of four interconnected planes, each serving a distinct purpose: the Management Plane handles agent provisioning and lifecycle; the Control Plane defines and enforces policies; the Data Plane executes actual agent operations; and the Security Plane manages authentication and authorization.
The Management Plane oversees the complete lifecycle of agents from creation through retirement. It handles deployment of new agent instances, scaling decisions based on workload, version updates, configuration management, and decommissioning. Operators interact primarily through the Management Plane using APIs or dashboards, issuing commands like "deploy 10 instances of recommendation-agent" or "scale down search-agent by 30%". This plane maintains metadata about all active agents and their current state.
The Control Plane defines what agents are allowed to do. It stores policies as rules—such as "search-agent can query database X but not database Y" or "recommendation-agent cannot make purchases over 100 dollars"—and enforces these rules. Policies can be static (unchanging) or dynamic (adapting to conditions). The Control Plane evaluates policy compliance before each agent action. When an agent attempts an operation, the Control Plane intercepts the request, checks the policy store, and either permits or denies it.
The Data Plane is where the agent actually operates. It includes the agent's computational runtime, memory, access to external APIs and databases, and the communication channels with other systems. The Data Plane does not make decisions—it executes them, having already passed Control Plane validation. This separation is crucial for security: even if an agent is compromised, it cannot bypass the Control Plane's enforcement.
The Security Plane ensures that only authorized operators and agents can perform actions. It handles agent authentication (proving the agent is who it claims), operator authentication (proving the human is authorized), and authorization (determining what each principal can do). The Security Plane maintains audit logs of all policy violations and access decisions, critical for compliance and incident investigation.
Control Plane Architecture Overview
Each plane has a single responsibility. The Data Plane doesn't decide policy; the Control Plane doesn't execute operations. This separation makes the system easier to test, audit, and secure. If there's a bug in policy enforcement, it doesn't corrupt agent state or data.
Policy Language Example (Rego/OPA)
Implementation Patterns
Deploy a control enforcement sidecar alongside each agent instance. The sidecar intercepts all outbound requests and checks policies before forwarding. Advantages: fine-grained control, offline policy evaluation. Disadvantages: increased resource overhead.
Route all agent communications through a central policy gateway. The gateway evaluates policies and forwards permitted requests. Advantages: centralized audit, simpler debugging. Disadvantages: potential bottleneck at scale.
Embed policy evaluation directly in the agent runtime. Policies are downloaded and cached locally; the agent evaluates them before each action. Advantages: low latency, resilient to control plane outages. Disadvantages: harder to update policies globally.
Agent Operations in Production
210 minutes
Running AI agents reliably in production requires careful attention to deployment strategies, continuous health monitoring, resource optimization, and safe update procedures. Unlike batch jobs that run once and exit, agents are long-lived processes that must remain operational for extended periods while adapting to changing workloads and handling failures gracefully.
Deployment and scaling of agents involves selecting the right infrastructure, configuring resource requests and limits, and setting up autoscaling policies. Kubernetes is the de facto standard for container orchestration, providing declarative deployment specifications, automatic restart of failed pods, and resource management. When deploying agents, you specify CPU and memory requirements, health check endpoints, and scaling thresholds. The scheduler then places agent instances across available nodes, monitoring their resource consumption continuously.
Health monitoring for agents goes beyond standard application metrics. Agents need to report not just whether they're running, but whether they're functioning correctly: Are they responding to requests? Are their decision outputs reasonable? Are they stuck in error loops? Health checks typically include readiness probes that verify the agent is ready to serve, liveness probes that confirm the agent isn't deadlocked or in a bad state, and application-specific checks that validate business logic. Self-healing mechanisms automatically restart unhealthy instances or trigger alerts for human intervention.
Resource management ensures agents run efficiently without consuming excessive cloud resources. This includes setting CPU and memory limits to prevent runaway resource consumption, implementing request queues to backpressure when systems are overloaded, and using caching to reduce redundant computation. Cost optimization strategies like spot instances for non-critical agents, reserved capacity for baseline load, and auto-scaling based on demand help keep cloud bills manageable.
Update strategies determine how new versions of agents are rolled out. Blue-Green deployment creates a parallel environment with the new version, tests it thoroughly, then switches traffic atomically. Canary deployment gradually shifts traffic from old to new versions, catching issues early in limited scope. Rolling deployment updates instances sequentially, maintaining service availability throughout. Each strategy has tradeoffs: Blue-Green requires double resources but offers instant rollback; Canary is slower but catches problems early; Rolling is efficient but less predictable.
Kubernetes Deployment Configuration
Implement both readiness and liveness probes. Readiness indicates the agent is warmed up and ready to handle requests; liveness indicates the agent process is still functional. An agent might be live but not ready (e.g., still loading ML model). Tune timeouts based on your agent's initialization speed.
Canary Deployment Strategy
Update Strategies Comparison
| Strategy | Speed | Risk Detection | Resource Impact |
|---|---|---|---|
| Blue-Green | Very Fast | Pre-deploy testing only | 2x resources needed |
| Canary | Slow (gradual) | Production metrics | Small overhead |
| Rolling | Medium | Gradual exposure | Minimal overhead |
Monitoring, Logging, and Observability
200 minutes
Observability is the ability to understand system behavior from its outputs. For AI agents, this means collecting and correlating metrics, logs, and traces that reveal what the agent is doing, why it's doing it, and whether its outputs are correct. Unlike traditional software where observability is nice-to-have, for agents it's essential—bad decisions are often silent, making detection difficult without comprehensive observability.
An Observability Stack typically consists of four components: metrics (time-series data about system behavior), logs (detailed records of events), traces (end-to-end request flows), and profiles (resource consumption analysis). Prometheus is the industry standard for metrics collection, Elasticsearch for log aggregation, Jaeger for distributed tracing, and Grafana for visualization. These tools work together: a high error rate in metrics triggers investigation of logs and traces to root-cause the issue.
Critical metrics for agent health include latency (how long requests take), throughput (requests per second), error rate (failed requests), and business metrics (e.g., recommendations accepted, revenue generated). For AI agents specifically, you also need model-specific metrics: inference time, cache hit rate, model staleness (how old the deployed model is), and distribution shift detection (detecting when input patterns diverge from training data). These metrics feed dashboards that operators monitor continuously and trigger alerts when thresholds are violated.
Distributed tracing follows requests through a system, connecting logs across multiple services. For agents making API calls, querying databases, and invoking other agents, tracing shows the complete journey of a request and identifies bottlenecks. Each trace contains spans representing individual operations, tagged with metadata like agent_id, operation_type, and result. When an agent produces an unexpected decision, tracing reveals the exact path taken and where decisions were made.
Alerting converts observations into actions. Based on metric thresholds, anomalies, or log patterns, alerts notify on-call engineers via email, Slack, PagerDuty, or automated incident systems. Well-designed alerts are actionable (they guide engineers toward solutions) and have low false positive rates (alerts people only when something really needs attention). Too many alerts cause alert fatigue; too few leave problems undetected.
OpenTelemetry Instrumentation Example
Track: (1) Request volume and latency percentiles (p50, p95, p99), (2) Error rates by error type, (3) Model inference latency separately, (4) Cache hit rates, (5) Policy violations and denials, (6) Resource utilization, (7) Output quality metrics (user feedback, satisfaction).
Prometheus Metrics Configuration
Alert Response Automation
Use tools like PagerDuty, Opsgenie, or custom webhooks to automatically trigger responses based on alerts. For example:
Security and Authorization in Control
200 minutes
Security for AI agents involves multiple layers: agent authentication (proving the agent is legitimate), operator authentication (proving the human is authorized), authorization (determining what each principal can do), and audit logging (recording what happened). Without these layers, compromised agents or malicious operators could cause significant damage by making unauthorized transactions, accessing sensitive data, or modifying other agents' configurations.
Agent Authentication typically uses cryptographic credentials: each agent receives a certificate or token signed by a trusted authority. When an agent makes a request, it presents this credential, which is verified before the request proceeds. For Kubernetes-based agents, mTLS (mutual TLS) ensures bidirectional authentication—both client and server verify each other's identity. For API-based agents, bearer tokens or OAuth2 flows are common. Credentials must be rotated regularly and revoked immediately if compromised.
Role-Based Access Control (RBAC) assigns permissions based on an agent's role. For example, a "search-agent" role might have permissions to query indices and read user profiles, while a "payment-agent" role has permission to process transactions up to certain limits. RBAC simplifies permission management at scale: instead of assigning permissions individually to each agent, you assign them to roles and add agents to roles. Changes to role permissions instantly apply to all agents with that role.
Attribute-Based Access Control (ABAC) extends RBAC by making access decisions based on attributes—properties of the agent, resource, environment, or action. For instance, "allow if agent_team == 'payments' AND request.amount < 10000 AND request.time < business_hours AND request.source_ip in VPC". ABAC is more flexible but more complex to implement and audit. Most organizations use a hybrid: RBAC for coarse permissions, ABAC for fine-grained control.
Audit logging records every significant action: agent authentication, authorization checks, policy evaluations, API calls. Audit logs are immutable (cannot be modified after creation) and sent to a centralized system separate from operational logs. They serve multiple purposes: compliance (proving you followed regulations), forensics (understanding what happened in an incident), and anomaly detection (detecting unusual patterns). For critical agents, audit logs should include decision rationale—why did the agent choose this action?
Agent isolation (sandboxing) restricts what a compromised agent can affect. Kubernetes provides isolation through namespace boundaries and network policies. Containers provide process isolation. Resource limits prevent resource exhaustion attacks. Never trust the agent's self-reported state—always verify through independent means. A compromised agent might report "I'm running fine" while secretly making unauthorized changes.
mTLS Agent Authentication
RBAC Configuration Example
Never trust any request without verification. Implement: (1) Authentication for every request, (2) Authorization before every operation, (3) Encryption in transit (TLS) and at rest, (4) Audit logging of all security-relevant events, (5) Regular security audits and penetration testing.
Audit Logging Implementation
Security Isolation Architecture
Each agent type in separate Kubernetes namespace with network policies
Run containers with read-only root filesystem, drop privileged capabilities, no host access
CPU, memory, and disk quotas prevent denial-of-service attacks
Agents can only call whitelisted endpoints; no data exfiltration possible
Credentials injected at runtime, never stored in images or config files
Guardrails, Constraints, and Backup Controls
210 minutes
Guardrails are the protective mechanisms that prevent agents from causing harm, even if their reasoning fails or they're compromised. Unlike authorization controls that check permissions before actions, guardrails constrain what actions are even possible. They're the difference between an agent that's allowed to make large purchases versus an agent that's technically allowed but cannot physically make purchases over a certain amount—the latter is safer.
Setting boundaries means defining the scope and limits of what an agent can do. Mission scope defines the agent's intended purpose (e.g., "recommend products to users" or "process refund requests"). Constraints define hard limits on actions (e.g., "maximum transaction is $10,000" or "cannot access customer SSN"). Boundaries should be narrow—the agent can only do what's necessary for its mission, nothing more. Broad permissions are a security risk; they create opportunities for misuse or unintended consequences.
Rate limiting and resource quotas prevent agents from overwhelming shared resources. A recommendation agent that queries the database thousands of times per second could cause performance degradation for all users. Rate limiting imposes per-agent or per-resource limits (e.g., "max 100 requests per second per agent"). Resource quotas limit total resource consumption (e.g., "agents can collectively use max 50% of cluster CPU"). Both mechanisms have graceful degradation: when a limit is reached, the agent receives an error response rather than crashing the system.
Human-in-the-loop workflows insert human approval for high-risk actions. An agent might autonomously handle routine customer service requests but require human approval for refunds over a threshold, policy changes, or deletion of important data. This combines the speed of automation with human judgment for critical decisions. The implementation requires careful UX design—approvals that take too long block progress, while insufficient review defeats the purpose.
Rollback and emergency stops provide last-resort recovery when things go wrong. Automatic rollback reverts to a previous known-good state when errors or anomalies are detected. Emergency stops are manual shutdowns—an operator presses a button and the agent stops accepting new requests, allowing in-flight requests to complete and then shutting down cleanly. These mechanisms must be fast and reliable; they're critical during incidents. Test them regularly.
Boundary and Mission Scope Definition
Boundaries are most effective when enforced at multiple layers: (1) In the agent's decision logic, (2) At the API gateway, (3) In the database access layer, (4) Through resource limits. This defense-in-depth approach ensures that even if one layer fails, others still protect the system.
Rate Limiting and Resource Quota Implementation
Human-in-the-Loop Workflow
Automatic Rollback and Emergency Stop
Multi-Agent Orchestration
180 minutes
Multi-agent systems combine multiple specialized agents, each focusing on a specific capability or domain. A customer service system might have a classification agent that determines issue type, a retrieval agent that finds relevant documentation, a response-generation agent that drafts replies, and a quality agent that ensures responses meet standards. Orchestrating these agents—coordinating their work, ensuring they reach consensus, handling failures—is more complex than managing individual agents.
Coordination patterns define how agents interact. Sequential coordination has agents work one after another: agent A produces output that becomes agent B's input. This is simple but slow and inflexible if agent B's output doesn't meet requirements. Parallel coordination has agents work simultaneously on different aspects of a problem, then a coordinator combines results. This is faster but requires careful result merging. Hierarchical coordination assigns a leader agent that decomposes the problem and assigns subtasks to worker agents, collecting and synthesizing their results.
Consensus mechanisms help multiple agents agree on a decision. Voting has each agent vote, and the majority decision wins—simple but can create ties and ignores minority perspectives. Consensus through discussion has agents exchange information iteratively until they reach agreement. Consensus scoring has agents score options independently, with highest average score winning. The choice depends on problem type: voting works for classification (which category?), scoring for ranking (which option is best?), and discussion for complex decisions requiring justification.
Event-driven architecture decouples agents through asynchronous events. An agent publishes an event when it completes work; other interested agents subscribe to that event type and react. This loosens coupling—agents don't need to know about each other, only about event topics they care about. Message brokers like Kafka ensure reliable event delivery even if subscribers are temporarily unavailable. This pattern scales well and enables complex workflows.
Workflow engines and DAG (Directed Acyclic Graph) execution provide structured orchestration. You define a DAG where nodes are tasks (agent executions) and edges represent dependencies. The engine executes nodes in topological order, respecting dependencies. This is powerful for complex workflows but less flexible than dynamic coordination where agents decide next steps based on results.
Multi-Agent Coordination Patterns
For critical decisions, use confidence-weighted voting: each agent provides not just a vote but a confidence score. Results with high consensus (all agents confident and agreeing) are more reliable than results where agents barely agree. Log confidence metrics for monitoring.
Event-Driven Agent Architecture
DAG-Based Workflow Execution (Airflow/Prefect)
Consensus Voting Mechanisms
Most agents agree on option. Simple but ties possible. Best for binary or multi-class decisions.
Each agent provides confidence score. Result = weighted average of votes. Advantages: respects agent certainty. Disadvantages: computational overhead.
Agents exchange arguments, update beliefs, repeat until convergence. Most robust but slowest. Good for complex decisions.
Leading option wins after timeout. Fast, handles non-responding agents. Risk of poor minority being ignored.
Case Studies and Troubleshooting
240 minutes
Real-world AI agent systems face challenges that textbook examples rarely address. This module examines two detailed case studies from different domains—e-commerce and autonomous systems—highlighting the control plane architecture decisions, operational challenges, and lessons learned. Understanding how others have solved these problems accelerates your own implementation and helps you anticipate pitfalls.
Case Study 1: E-Commerce Agent Control System involves multiple specialized agents: a product recommendation agent suggesting items to customers, an inventory agent managing stock levels, a pricing agent adjusting prices dynamically based on demand, and a fraud detection agent flagging suspicious orders. These agents must coordinate without stepping on each other—the recommendation agent shouldn't recommend out-of-stock items, the pricing agent shouldn't crash sales from competitor moves, the fraud agent needs to balance false positives (rejecting good customers) against false negatives (allowing fraud).
In this system, the control plane implements strict guardrails: recommendations are checked against real-time inventory before presentation to the user, pricing adjustments are bounded (not more than 20% change in an hour), and fraud agent alerts trigger escalation to humans for orders above certain thresholds. The event-driven architecture means when inventory is low, the inventory agent publishes an event that the recommendation agent consumes to avoid suggesting scarce items. Monitoring is critical—unusual patterns like sudden demand shifts or coordinated fraud attempts are detected through anomaly detection algorithms and trigger alerts.
Case Study 2: Autonomous Vehicle Decision Control is more safety-critical. Multiple decision agents contribute to driving decisions: a perception agent processes sensor data, a planning agent generates trajectory options, a prediction agent forecasts other vehicles' movements, and a safety agent validates that trajectories won't cause collisions. Unlike e-commerce where errors are recoverable (recommend wrong product, customer just doesn't buy), autonomous driving errors can cause accidents. The control plane must be extremely conservative—actions are denied unless safety agent explicitly approves them.
In autonomous driving, the control system implements multiple redundancy layers: different sensors validate the same phenomena, multiple algorithms independently compute trajectories, and a safety monitor verifies every decision. A human operator can always override the agents with emergency controls. The system logs every decision at the millisecond level, enabling reconstruction of accidents for investigation. Updates to decision models are validated on massive datasets before deployment, and even then, rollouts are extremely conservative—a new model might only control a small geographic region or specific times of day initially.
Common troubleshooting scenarios include deadlock (agents waiting for each other indefinitely), cascading failures (one agent's failure triggering failures in others), policy conflicts (policies that contradict each other), and performance degradation under load. Understanding these patterns and their remediation accelerates incident response and prevents recurrence.
Case Study 1: E-Commerce Control Architecture
Case Study 2: Autonomous Vehicle Decision Control
Both systems prioritize safety through redundancy and explicit deny-by-default policies. The e-commerce system recovers gracefully from failures (wrong recommendation is not catastrophic). The autonomous vehicle system fails safely (worst case: stop driving). Design your control plane with similar principles: identify your failure modes, implement appropriate safeguards, and test extensively.
Common Troubleshooting Scenarios
Symptom: Requests stall indefinitely; agent logs show waiting for external resource.
Root Causes: Circular dependencies (agent A waits for B, B waits for A), resource exhaustion (all threads blocked), slow external service.
Solutions: Implement request timeouts (no request waits forever), add deadlock detection in logging, use lock-free coordination patterns, redesign dependencies to be acyclic, add queue backpressure to reject new work when saturated.
Symptom: One agent fails, others follow in domino effect.
Root Causes: Hard dependencies without fallbacks, shared critical resource, retry storms (failed requests retried endlessly).
Solutions: Implement circuit breakers (stop calling failing services temporarily), add fallback behaviors for each agent, degrade gracefully (accept lower quality than fail completely), implement exponential backoff with jitter for retries, isolate failures to minimize blast radius.
Symptom: Agent cannot execute because multiple policies contradict each other.
Root Causes: Overlapping policy scopes, policies added over time without deconfliction, multiple policy sources (different teams).
Solutions: Test policies before deployment against representative workloads, implement policy conflict detection tools, establish policy governance process, use policy versioning for rollback, maintain policy documentation and owner contacts.
Symptom: System performs well at normal load, but latency explodes when load increases.
Root Causes: Missing indexes in databases, unbounded queues, quadratic algorithms, lock contention, garbage collection pauses.
Solutions: Load test before deployment, implement request queuing with backpressure, add circuit breakers to reject excess load gracefully, monitor latency percentiles (p95, p99) not just averages, profile with realistic workloads, implement caching for hot data.
Troubleshooting Decision Tree
Industry Best Practices Summary
Assume every component will fail. Build redundancy, circuit breakers, and graceful degradation. Test failure scenarios regularly through chaos engineering.
Comprehensive logging, metrics, and tracing are non-negotiable. You cannot fix what you cannot see. Invest in observability from day one.
Automate operations that are safe to automate (scaling, restarts, routine updates). Keep humans in the loop for risky decisions.
Version your models, policies, configurations, and infrastructure code. This enables rollback and auditing.
Use canary deployments, shadow traffic, and A/B testing to validate changes in production with limited blast radius.
Document architecture decisions, operational runbooks, and incident post-mortems. Share knowledge across teams to prevent recurrence.
Incident Post-Mortem Template
Frequently Asked Questions
What background do I need before starting this course?
Basic knowledge of distributed systems, familiarity with microservices architecture, and experience with APIs will be helpful. Prior exposure to Python or Go is valuable. The course assumes you understand fundamental concepts like networking, databases, and APIs; we focus on agent-specific orchestration, not these basics.
Does the course include hands-on projects?
Yes. The course includes four capstone projects: (1) Building a basic Control Plane from scratch, (2) Setting up an Observability Stack for agent monitoring, (3) Implementing security policies and RBAC, and (4) Designing and implementing a multi-agent orchestration system. Each project includes starter code and detailed requirements.
How is this different from a standard AI course?
This course focuses on operations and management of AI agents, not on training or improving models. We discuss how to run agents safely, reliably, and efficiently in production. Topics include deployment, monitoring, security, and coordination—the DevOps and SRE perspective on AI systems, not the ML research perspective.
Will we cover specific technologies?
Yes. We use Kubernetes for orchestration, Prometheus for metrics, Jaeger for distributed tracing, OpenTelemetry for instrumentation, and tools like OPA/Rego for policy enforcement. For LLM examples, we reference OpenAI, Anthropic, and local open-source models. The principles transfer to other stacks, but we provide concrete examples with these tools.
Is this course theoretical or practical?
It's 50/50. Each module includes conceptual lectures and architecture diagrams, plus live demonstrations with real code and tools. Lab sessions let you build and troubleshoot actual systems. We believe the best learning combines understanding principles with practical hands-on experience.
How much time should I dedicate to self-study?
Plan for 4-6 hours per week of self-study beyond live sessions: reviewing lecture materials, experimenting with code examples, and working on exercises. The capstone projects require an additional 15-20 hours each. Total time investment is typically 3-4 months for working professionals.
What will I receive upon completion?
You'll receive a course completion certificate, access to a GitHub repository with four production-ready projects you've built, and an architecture document for implementing agent control systems. This portfolio demonstrates concrete skills to employers and peers.
Is this course current for 2025?
Yes, the course is continuously updated. It covers cutting-edge models (GPT-4o, Claude 3.5, Gemini 2.0), modern agent frameworks (AutoGPT, LangChain, CrewAI), and current industry trends like agentic AI and multi-agent systems. Content is refreshed quarterly based on practitioner feedback and technology changes.