diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index c2ce7af0094ccab147f1cd1463cf7b9dd22fd6fa..9fce6b6c1d9fc133913bc775e0a4b1b2a2286c04 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -1477,6 +1477,32 @@ Input type: `AiAgentCreateInput`
 | <a id="mutationaiagentcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
 | <a id="mutationaiagentcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
 
+### `Mutation.aiAgentUpdate`
+
+DETAILS:
+**Introduced** in GitLab 16.10.
+**Status**: Experiment.
+
+Input type: `AiAgentUpdateInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationaiagentupdateagentid"></a>`agentId` | [`AiAgentID!`](#aiagentid) | ID of the agent. |
+| <a id="mutationaiagentupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationaiagentupdatename"></a>`name` | [`String`](#string) | Name of the agent. |
+| <a id="mutationaiagentupdateprojectpath"></a>`projectPath` | [`ID!`](#id) | Project to which the agent belongs. |
+| <a id="mutationaiagentupdateprompt"></a>`prompt` | [`String`](#string) | Prompt for the agent. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationaiagentupdateagent"></a>`agent` | [`AiAgent`](#aiagent) | Agent after mutation. |
+| <a id="mutationaiagentupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationaiagentupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
 ### `Mutation.alertSetAssignees`
 
 Input type: `AlertSetAssigneesInput`
diff --git a/ee/app/assets/javascripts/ml/ai_agents/components/agent_form.vue b/ee/app/assets/javascripts/ml/ai_agents/components/agent_form.vue
index 5eaebdd5aba9a1b46f1d9aecc4422b28d2007f73..e3d4701d2668d2118942ed94f90c37731ba95c33 100644
--- a/ee/app/assets/javascripts/ml/ai_agents/components/agent_form.vue
+++ b/ee/app/assets/javascripts/ml/ai_agents/components/agent_form.vue
@@ -29,6 +29,21 @@ export default {
       required: false,
       default: false,
     },
+    agentId: {
+      type: String,
+      required: false,
+      default: '',
+    },
+    agentNameValue: {
+      type: String,
+      required: false,
+      default: '',
+    },
+    agentPromptValue: {
+      type: String,
+      required: false,
+      default: '',
+    },
   },
   data() {
     return {
@@ -44,8 +59,8 @@ export default {
         },
       },
       formValues: {
-        name: '',
-        prompt: '',
+        name: this.agentNameValue,
+        prompt: this.agentPromptValue,
       },
     };
   },
@@ -53,6 +68,7 @@ export default {
     onSubmit() {
       this.$emit('submit', {
         projectPath: this.projectPath,
+        agentId: this.agentId,
         name: this.formValues.name,
         prompt: this.formValues.prompt,
       });
diff --git a/ee/app/assets/javascripts/ml/ai_agents/constants.js b/ee/app/assets/javascripts/ml/ai_agents/constants.js
index 97208891ccf7e4ac00bce91b45e1373625239cbf..289ae6e63f02617e0c8b6198b6725a935ae2e77e 100644
--- a/ee/app/assets/javascripts/ml/ai_agents/constants.js
+++ b/ee/app/assets/javascripts/ml/ai_agents/constants.js
@@ -3,9 +3,13 @@ import { s__ } from '~/locale';
 export const ROUTE_LIST_AGENTS = 'list';
 export const ROUTE_NEW_AGENT = 'create';
 export const ROUTE_SHOW_AGENT = 'show';
+export const ROUTE_EDIT_AGENT = 'edit';
 
 export const I18N_AGENT_NAME_LABEL = s__('AIAgent|Agent name');
 export const I18N_PROMPT_LABEL = s__('AIAgent|Prompt (optional)');
 export const I18N_CREATE_AGENT = s__('AIAgent|Create agent');
+export const I18N_UPDATE_AGENT = s__('AIAgent|Update agent');
+export const I18N_EDIT_AGENT = s__('AIAgent|Edit Ai Agent');
 
+export const I18N_DEFAULT_NOT_FOUND_ERROR = s__('AIAgents|The requested agent was not found.');
 export const I18N_DEFAULT_SAVE_ERROR = s__('AIAgents|An error has occurred when saving the agent.');
diff --git a/ee/app/assets/javascripts/ml/ai_agents/graphql/mutations/update_ai_agent.mutation.graphql b/ee/app/assets/javascripts/ml/ai_agents/graphql/mutations/update_ai_agent.mutation.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..d802d1b6c6190f88d474b42aa285deb059e06487
--- /dev/null
+++ b/ee/app/assets/javascripts/ml/ai_agents/graphql/mutations/update_ai_agent.mutation.graphql
@@ -0,0 +1,17 @@
+mutation updateAiAgent($projectPath: ID!, $agentId: AiAgentID!, $name: String, $prompt: String) {
+  aiAgentUpdate(
+    input: { projectPath: $projectPath, agentId: $agentId, name: $name, prompt: $prompt }
+  ) {
+    agent {
+      id
+      routeId
+      name
+      latestVersion {
+        id
+        prompt
+        model
+      }
+    }
+    errors
+  }
+}
diff --git a/ee/app/assets/javascripts/ml/ai_agents/graphql/queries/get_latest_ai_agent_version.query.graphql b/ee/app/assets/javascripts/ml/ai_agents/graphql/queries/get_latest_ai_agent_version.query.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..e09b71f7ab07bb2fe6e287cee74390b1cdaca2b5
--- /dev/null
+++ b/ee/app/assets/javascripts/ml/ai_agents/graphql/queries/get_latest_ai_agent_version.query.graphql
@@ -0,0 +1,14 @@
+query getLatestAiAgentVersion($fullPath: ID!, $agentId: AiAgentID!) {
+  project(fullPath: $fullPath) {
+    id
+    aiAgent(id: $agentId) {
+      id
+      name
+      latestVersion {
+        id
+        prompt
+        model
+      }
+    }
+  }
+}
diff --git a/ee/app/assets/javascripts/ml/ai_agents/router.js b/ee/app/assets/javascripts/ml/ai_agents/router.js
index e384cb49e4e71f46ec9b7d9d0f3a1ff2c3f5938b..0ea65dcfcbe6235ee7d88d77ad1d8fd5b98817f6 100644
--- a/ee/app/assets/javascripts/ml/ai_agents/router.js
+++ b/ee/app/assets/javascripts/ml/ai_agents/router.js
@@ -3,7 +3,13 @@ import VueRouter from 'vue-router';
 import ListAgents from 'ee/ml/ai_agents/views/list_agents.vue';
 import ShowAgent from 'ee/ml/ai_agents/views/show_agent.vue';
 import CreateAgent from 'ee/ml/ai_agents/views/create_agent.vue';
-import { ROUTE_LIST_AGENTS, ROUTE_NEW_AGENT, ROUTE_SHOW_AGENT } from './constants';
+import EditAgent from 'ee/ml/ai_agents/views/edit_agent.vue';
+import {
+  ROUTE_LIST_AGENTS,
+  ROUTE_NEW_AGENT,
+  ROUTE_SHOW_AGENT,
+  ROUTE_EDIT_AGENT,
+} from './constants';
 
 Vue.use(VueRouter);
 
@@ -27,6 +33,11 @@ export default function createRouter(base) {
         path: '/:agentId',
         component: ShowAgent,
       },
+      {
+        name: ROUTE_EDIT_AGENT,
+        path: '/:agentId/edit',
+        component: EditAgent,
+      },
     ],
   });
 
diff --git a/ee/app/assets/javascripts/ml/ai_agents/views/edit_agent.vue b/ee/app/assets/javascripts/ml/ai_agents/views/edit_agent.vue
new file mode 100644
index 0000000000000000000000000000000000000000..db2727dbae09d97758be587c48ce0465269a3144
--- /dev/null
+++ b/ee/app/assets/javascripts/ml/ai_agents/views/edit_agent.vue
@@ -0,0 +1,129 @@
+<script>
+import { GlExperimentBadge, GlLoadingIcon, GlAlert, GlEmptyState } from '@gitlab/ui';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+import * as Sentry from '~/sentry/sentry_browser_wrapper';
+import getLatestAiAgentVersion from '../graphql/queries/get_latest_ai_agent_version.query.graphql';
+import AgentForm from '../components/agent_form.vue';
+import updateAiAgent from '../graphql/mutations/update_ai_agent.mutation.graphql';
+import {
+  I18N_UPDATE_AGENT,
+  I18N_DEFAULT_SAVE_ERROR,
+  I18N_DEFAULT_NOT_FOUND_ERROR,
+  I18N_EDIT_AGENT,
+} from '../constants';
+
+export default {
+  name: 'EditAiAgent',
+  components: {
+    TitleArea,
+    GlExperimentBadge,
+    GlLoadingIcon,
+    GlAlert,
+    AgentForm,
+    GlEmptyState,
+  },
+  I18N_UPDATE_AGENT,
+  I18N_DEFAULT_SAVE_ERROR,
+  I18N_DEFAULT_NOT_FOUND_ERROR,
+  I18N_EDIT_AGENT,
+  inject: ['projectPath'],
+  data() {
+    return {
+      errorMessage: '',
+      loading: false,
+    };
+  },
+  apollo: {
+    latestAgentVersion: {
+      query: getLatestAiAgentVersion,
+      variables() {
+        return this.queryVariables;
+      },
+      update(data) {
+        return data.project?.aiAgent ?? {};
+      },
+      error(error) {
+        this.errorMessage = error.message;
+        Sentry.captureException(error);
+      },
+    },
+  },
+  computed: {
+    isLoading() {
+      return this.$apollo.queries.latestAgentVersion.loading;
+    },
+    queryVariables() {
+      return {
+        fullPath: this.projectPath,
+        agentId: `gid://gitlab/Ai::Agent/${this.$route.params.agentId}`,
+      };
+    },
+  },
+  methods: {
+    async updateAgent(requestData) {
+      this.errorMessage = '';
+      this.loading = true;
+      try {
+        const { data } = await this.$apollo.mutate({
+          mutation: updateAiAgent,
+          variables: requestData,
+        });
+
+        this.loading = false;
+
+        const [error] = data?.aiAgentUpdate?.errors || [];
+
+        if (error) {
+          this.errorMessage = data.aiAgentUpdate.errors.join(', ');
+        } else {
+          this.$router.push({
+            name: 'show',
+            params: { agentId: data?.aiAgentUpdate?.agent?.routeId },
+          });
+        }
+      } catch (error) {
+        Sentry.captureException(error);
+        this.errorMessage = this.$options.I18N_DEFAULT_SAVE_ERROR;
+        this.loading = false;
+      }
+    },
+  },
+};
+</script>
+
+<template>
+  <div>
+    <gl-empty-state
+      v-if="latestAgentVersion === undefined"
+      :title="$options.I18N_DEFAULT_NOT_FOUND_ERROR"
+    />
+
+    <gl-loading-icon v-else-if="isLoading" size="lg" class="gl-my-5" />
+
+    <gl-alert v-else-if="errorMessage" :dismissible="false" variant="danger" class="gl-mb-3">
+      {{ errorMessage }}
+    </gl-alert>
+
+    <div v-else>
+      <title-area>
+        <template #title>
+          <div class="gl-flex-grow-1 gl-display-flex gl-align-items-center">
+            <span>{{ $options.I18N_EDIT_AGENT }}: {{ latestAgentVersion.name }}</span>
+            <gl-experiment-badge />
+          </div>
+        </template>
+      </title-area>
+
+      <agent-form
+        :project-path="projectPath"
+        :agent-id="latestAgentVersion.id"
+        :agent-name-value="latestAgentVersion.name"
+        :agent-prompt-value="latestAgentVersion.latestVersion.prompt"
+        :button-label="$options.I18N_UPDATE_AGENT"
+        :error-message="errorMessage"
+        :loading="loading"
+        @submit="updateAgent"
+      />
+    </div>
+  </div>
+</template>
diff --git a/ee/app/graphql/ee/types/mutation_type.rb b/ee/app/graphql/ee/types/mutation_type.rb
index fe38901c98e76e7e0b6ca2252588799bb53e7ea8..42cd65e60f8f8c7efd6716ead0f5eb1366a1a59d 100644
--- a/ee/app/graphql/ee/types/mutation_type.rb
+++ b/ee/app/graphql/ee/types/mutation_type.rb
@@ -152,6 +152,7 @@ module MutationType
         mount_mutation ::Mutations::AuditEvents::Streaming::HTTP::NamespaceFilters::Create
         mount_mutation ::Mutations::AuditEvents::Streaming::HTTP::NamespaceFilters::Delete
         mount_mutation ::Mutations::Ai::Agents::Create, alpha: { milestone: '16.8' }
+        mount_mutation ::Mutations::Ai::Agents::Update, alpha: { milestone: '16.10' }
         mount_mutation ::Mutations::ComplianceManagement::Standards::RefreshAdherenceChecks
         mount_mutation ::Mutations::Groups::SavedReplies::Create, alpha: { milestone: '16.10' }
         mount_mutation ::Mutations::Groups::SavedReplies::Update, alpha: { milestone: '16.10' }
diff --git a/ee/app/graphql/mutations/ai/agents/update.rb b/ee/app/graphql/mutations/ai/agents/update.rb
new file mode 100644
index 0000000000000000000000000000000000000000..001e4d3bc79d4dd0c19b268acacd758e0a8dc796
--- /dev/null
+++ b/ee/app/graphql/mutations/ai/agents/update.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Mutations
+  module Ai
+    module Agents
+      class Update < Base
+        graphql_name 'AiAgentUpdate'
+
+        include FindsProject
+
+        argument :agent_id, Types::GlobalIDType[::Ai::Agent],
+          required: true,
+          description: 'ID of the agent.'
+
+        argument :name, GraphQL::Types::String,
+          required: false,
+          description: 'Name of the agent.'
+
+        argument :prompt, GraphQL::Types::String,
+          required: false,
+          description: 'Prompt for the agent.'
+
+        def resolve(**args)
+          authorized_find!(args[:project_path])
+          agent = ::Gitlab::Graphql::Lazy.force(GitlabSchema.find_by_gid(args[:agent_id]))
+
+          updated_agent = ::Ai::Agents::UpdateAgentService.new(agent, args[:name], args[:prompt]).execute
+
+          {
+            agent: updated_agent.errors.any? ? nil : updated_agent,
+            errors: errors_on_object(updated_agent)
+          }
+        end
+      end
+    end
+  end
+end
diff --git a/ee/app/models/ai/agent.rb b/ee/app/models/ai/agent.rb
index d675ee1eab7d36397020846c4ff977428bbb0c2e..950567a8dd9a0156007c4c68bbcdaeff4b2f19fa 100644
--- a/ee/app/models/ai/agent.rb
+++ b/ee/app/models/ai/agent.rb
@@ -15,7 +15,7 @@ class Agent < ApplicationRecord
 
     belongs_to :project
     has_many :versions, class_name: 'Ai::AgentVersion'
-    has_one :latest_version, -> { latest_by_agent }, class_name: 'Ai::AgentVersion', inverse_of: :agent
+    has_one :latest_version, -> { latest_by_agent }, class_name: 'Ai::AgentVersion', inverse_of: :agent, validate: true
 
     scope :including_project, -> { includes(:project) }
     scope :for_project, ->(project) { where(project_id: project.id) }
diff --git a/ee/app/services/ai/agents/update_agent_service.rb b/ee/app/services/ai/agents/update_agent_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fdd777890e1305fa815e30520efc0bc7879f3612
--- /dev/null
+++ b/ee/app/services/ai/agents/update_agent_service.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Ai
+  module Agents
+    class UpdateAgentService < BaseService
+      def initialize(agent, name, prompt)
+        @agent = agent
+        @name = name
+        @prompt = prompt
+      end
+
+      def execute
+        Ai::Agent.transaction do
+          @agent.name = @name unless @name.nil?
+          @agent.latest_version.prompt = @prompt unless @prompt.nil?
+          @agent.save # this method doesn't raise if it fails so that we can show vailidation errors to the user
+        end
+
+        @agent
+      end
+    end
+  end
+end
diff --git a/ee/spec/frontend/ml/ai_agents/components/agent_form_spec.js b/ee/spec/frontend/ml/ai_agents/components/agent_form_spec.js
index e36e437ed8d532a17dad2801804fdc0331616042..86c9a4aac954aabcdd3b4a54aee6beecfd6b2175 100644
--- a/ee/spec/frontend/ml/ai_agents/components/agent_form_spec.js
+++ b/ee/spec/frontend/ml/ai_agents/components/agent_form_spec.js
@@ -1,4 +1,4 @@
-import { GlButton, GlFormInput, GlFormTextarea, GlAlert } from '@gitlab/ui';
+import { GlButton, GlFormInput, GlFormTextarea, GlAlert, GlFormFields } from '@gitlab/ui';
 import { mountExtended } from 'helpers/vue_test_utils_helper';
 import AgentForm from 'ee/ml/ai_agents/components/agent_form.vue';
 
@@ -21,6 +21,7 @@ describe('AI Agents Form', () => {
     });
   };
 
+  const findFormFields = () => wrapper.findComponent(GlFormFields);
   const findTextInput = () => wrapper.findComponent(GlFormInput);
   const findTextareaInput = () => wrapper.findComponent(GlFormTextarea);
   const findSubmitButton = () => wrapper.findComponent(GlButton);
@@ -60,6 +61,16 @@ describe('AI Agents Form', () => {
     expect(findSubmitButton().props('loading')).toBe(true);
   });
 
+  it('displays the input values when the props are supplied', () => {
+    createComponent({
+      agentNameValue: 'agent_1',
+      agentPromptValue: 'Do something',
+    });
+
+    expect(findFormFields().props('values').name).toEqual('agent_1');
+    expect(findFormFields().props('values').prompt).toEqual('Do something');
+  });
+
   it('emits an event with the form data when the form is submitted', async () => {
     createComponent();
 
@@ -70,6 +81,7 @@ describe('AI Agents Form', () => {
 
     expect(wrapper.emitted('submit')[0][0]).toEqual({
       projectPath: 'path/to/project',
+      agentId: '',
       name: 'agent_1',
       prompt: 'Do something',
     });
diff --git a/ee/spec/frontend/ml/ai_agents/graphql/mocks.js b/ee/spec/frontend/ml/ai_agents/graphql/mocks.js
index c0b3b2ed04bfb17e517fbe2ba2d3ff8909439b8c..e88da9bb3e081ab23846b1b48fe36a0f9089ec94 100644
--- a/ee/spec/frontend/ml/ai_agents/graphql/mocks.js
+++ b/ee/spec/frontend/ml/ai_agents/graphql/mocks.js
@@ -20,6 +20,34 @@ export const createAiAgentsResponses = {
   },
 };
 
+export const updateAiAgentsResponses = {
+  success: {
+    data: {
+      aiAgentUpdate: {
+        agent: {
+          id: 'gid://gitlab/Ai::Agent/1',
+          routeId: 2,
+          name: 'New name',
+          latestVersion: {
+            id: 'gid://gitlab/Ai::AgentVersion/1',
+            prompt: 'my prompt',
+            model: 'default',
+          },
+        },
+        errors: [],
+      },
+    },
+  },
+  validationFailure: {
+    data: {
+      aiAgentUpdate: {
+        agent: null,
+        errors: ['Name is invalid'],
+      },
+    },
+  },
+};
+
 export const listAiAgentsResponses = {
   data: {
     project: {
@@ -61,3 +89,36 @@ export const listAiAgentsEmptyResponses = {
     },
   },
 };
+
+export const getLatestAiAgentResponse = {
+  data: {
+    project: {
+      id: 'gid://gitlab/Project/1',
+      aiAgent: {
+        id: 'gid://gitlab/Ai::Agent/1',
+        routeId: 2,
+        name: 'agent-1',
+        versions: [
+          {
+            id: 'gid://gitlab/Ai::AgentVersion/1',
+            prompt: 'example prompt',
+            model: 'default',
+          },
+        ],
+        latestVersion: {
+          id: 'gid://gitlab/Ai::AgentVersion/1',
+          prompt: 'example prompt',
+          model: 'default',
+        },
+      },
+    },
+  },
+};
+
+export const getLatestAiAgentErrorResponse = {
+  errors: [
+    {
+      message: 'An error has occurred when loading the agent.',
+    },
+  ],
+};
diff --git a/ee/spec/frontend/ml/ai_agents/views/edit_agent_spec.js b/ee/spec/frontend/ml/ai_agents/views/edit_agent_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..b2ce89f1fd6398afd4f2b8e8612b1b2cffb31a76
--- /dev/null
+++ b/ee/spec/frontend/ml/ai_agents/views/edit_agent_spec.js
@@ -0,0 +1,196 @@
+import {
+  GlButton,
+  GlFormInput,
+  GlFormTextarea,
+  GlForm,
+  GlExperimentBadge,
+  GlFormFields,
+  GlAlert,
+  GlEmptyState,
+} from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import EditAgent from 'ee/ml/ai_agents/views/edit_agent.vue';
+import getLatestAiAgentVersionQuery from 'ee/ml/ai_agents/graphql/queries/get_latest_ai_agent_version.query.graphql';
+import updateAiAgentMutation from 'ee/ml/ai_agents/graphql/mutations/update_ai_agent.mutation.graphql';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+import {
+  updateAiAgentsResponses,
+  getLatestAiAgentResponse,
+  getLatestAiAgentErrorResponse,
+} from '../graphql/mocks';
+
+Vue.use(VueApollo);
+
+const push = jest.fn();
+const $router = {
+  push,
+};
+
+describe('ee/ml/ai_agents/views/edit_agent', () => {
+  let wrapper;
+  let apolloMocks;
+  const agentId = 1;
+
+  const createComponent = () => {
+    const apolloProvider = createMockApollo(apolloMocks);
+
+    wrapper = mountExtended(EditAgent, {
+      apolloProvider,
+      provide: { projectPath: 'path/to/project' },
+      mocks: {
+        $router,
+        $route: {
+          params: {
+            agentId,
+          },
+        },
+      },
+    });
+  };
+
+  const findTitleArea = () => wrapper.findComponent(TitleArea);
+  const findBadge = () => wrapper.findComponent(GlExperimentBadge);
+  const findButton = () => wrapper.findComponent(GlButton);
+  const findForm = () => wrapper.findComponent(GlForm);
+  const findInput = () => wrapper.findComponent(GlFormInput);
+  const findTextarea = () => wrapper.findComponent(GlFormTextarea);
+  const findFormFields = () => wrapper.findComponent(GlFormFields);
+  const findErrorAlert = () => wrapper.findComponent(GlAlert);
+  const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+
+  const submitForm = async () => {
+    findForm().vm.$emit('submit', { preventDefault: () => {} });
+    await waitForPromises();
+  };
+
+  describe('when the agent data has successfully loaded', () => {
+    beforeEach(async () => {
+      apolloMocks = [
+        [getLatestAiAgentVersionQuery, jest.fn().mockResolvedValueOnce(getLatestAiAgentResponse)],
+      ];
+      createComponent();
+      await waitForPromises();
+    });
+
+    it('renders the page title', () => {
+      expect(findTitleArea().text()).toContain('Edit Ai Agent');
+    });
+
+    it('displays the experiment badge', () => {
+      expect(findBadge().exists()).toBe(true);
+    });
+
+    it('renders the button', () => {
+      expect(findButton().text()).toBe('Update agent');
+    });
+
+    it('renders the form and expected inputs', () => {
+      expect(findForm().exists()).toBe(true);
+      expect(findInput().exists()).toBe(true);
+      expect(findTextarea().exists()).toBe(true);
+      expect(findFormFields().props('values').name).toEqual('agent-1');
+      expect(findFormFields().props('values').prompt).toEqual('example prompt');
+    });
+  });
+
+  describe('when the agent data fails to load', () => {
+    beforeEach(async () => {
+      apolloMocks = [
+        [
+          getLatestAiAgentVersionQuery,
+          jest.fn().mockResolvedValueOnce(getLatestAiAgentErrorResponse),
+        ],
+      ];
+      createComponent();
+      await waitForPromises();
+    });
+
+    it('displays an error', () => {
+      expect(findEmptyState().text()).toBe('The requested agent was not found.');
+    });
+  });
+
+  describe('when successfully updating the agent data', () => {
+    let resolver;
+
+    beforeEach(async () => {
+      resolver = jest.fn().mockResolvedValueOnce(updateAiAgentsResponses.success);
+      apolloMocks = [
+        [getLatestAiAgentVersionQuery, jest.fn().mockResolvedValueOnce(getLatestAiAgentResponse)],
+        [updateAiAgentMutation, resolver],
+      ];
+
+      createComponent();
+      await waitForPromises();
+    });
+
+    it('submits the update with correct parameters', async () => {
+      await findInput().vm.$emit('input', 'agent_1');
+      await findTextarea().vm.$emit('input', 'Do something');
+
+      await submitForm();
+
+      expect(resolver).toHaveBeenLastCalledWith(
+        expect.objectContaining({
+          agentId: 'gid://gitlab/Ai::Agent/1',
+          projectPath: 'path/to/project',
+          name: 'agent_1',
+          prompt: 'Do something',
+        }),
+      );
+    });
+
+    it('navigates to the new page when result is successful', async () => {
+      await findInput().vm.$emit('input', 'agent_1');
+      await findTextarea().vm.$emit('input', 'Do something');
+
+      await submitForm();
+
+      expect($router.push).toHaveBeenCalledWith(
+        expect.objectContaining({
+          name: 'show',
+          params: { agentId: 2 },
+        }),
+      );
+    });
+  });
+
+  describe('when updating the agent data fails', () => {
+    it('shows errors when result is a top level error', async () => {
+      const error = new Error('Failure!');
+      const resolver = jest.fn().mockRejectedValue({ error });
+      apolloMocks = [
+        [getLatestAiAgentVersionQuery, jest.fn().mockResolvedValueOnce(getLatestAiAgentResponse)],
+        [updateAiAgentMutation, resolver],
+      ];
+
+      createComponent();
+      await waitForPromises();
+
+      await submitForm();
+
+      expect(findErrorAlert().text()).toBe('An error has occurred when saving the agent.');
+      expect($router.push).not.toHaveBeenCalled();
+    });
+
+    it('shows errors when result is a validation error', async () => {
+      const resolver = jest.fn().mockResolvedValueOnce(updateAiAgentsResponses.validationFailure);
+
+      apolloMocks = [
+        [getLatestAiAgentVersionQuery, jest.fn().mockResolvedValueOnce(getLatestAiAgentResponse)],
+        [updateAiAgentMutation, resolver],
+      ];
+
+      createComponent();
+      await waitForPromises();
+      await submitForm();
+
+      expect(findErrorAlert().text()).toBe('Name is invalid');
+      expect($router.push).not.toHaveBeenCalled();
+    });
+  });
+});
diff --git a/ee/spec/requests/api/graphql/ai/agents/update_spec.rb b/ee/spec/requests/api/graphql/ai/agents/update_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..cb5a5b12e81da104229ce31f2129a8b1d66336f4
--- /dev/null
+++ b/ee/spec/requests/api/graphql/ai/agents/update_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Update an AI agent', feature_category: :mlops do
+  include GraphqlHelpers
+
+  let_it_be(:agent_version) { create(:ai_agent_version) }
+  let_it_be(:agent) { agent_version.agent }
+  let_it_be(:project) { agent.project }
+  let_it_be(:current_user) { project.owner }
+
+  let(:input) { { project_path: project.full_path, agent_id: agent.to_global_id, name: name, prompt: prompt } }
+  let(:name) { 'some_name' }
+  let(:prompt) { 'A prompt' }
+
+  let(:mutation) { graphql_mutation(:ai_agent_update, input) }
+  let(:mutation_response) { graphql_mutation_response(:ai_agent_update) }
+
+  before do
+    stub_licensed_features(ai_agents: true)
+  end
+
+  context 'when user is not allowed write changes' do
+    before do
+      allow(Ability).to receive(:allowed?).and_call_original
+      allow(Ability).to receive(:allowed?)
+                          .with(current_user, :write_ai_agents, project)
+                          .and_return(false)
+    end
+
+    it_behaves_like 'a mutation that returns a top-level access error'
+  end
+
+  context 'when user is allowed write changes' do
+    it 'updates an agent' do
+      post_graphql_mutation(mutation, current_user: current_user)
+
+      expect(response).to have_gitlab_http_status(:success)
+      expect(mutation_response['agent']).to include(
+        'name' => name
+      )
+    end
+
+    context 'when name is invalid' do
+      err_msg = "Name is invalid"
+      let(:name) { 'invalid name' }
+
+      it_behaves_like 'a mutation that returns errors in the response', errors: [err_msg]
+    end
+  end
+end
diff --git a/ee/spec/services/ai/ai/agents/create_agent_service_spec.rb b/ee/spec/services/ai/agents/create_agent_service_spec.rb
similarity index 100%
rename from ee/spec/services/ai/ai/agents/create_agent_service_spec.rb
rename to ee/spec/services/ai/agents/create_agent_service_spec.rb
diff --git a/ee/spec/services/ai/agents/update_agent_service_spec.rb b/ee/spec/services/ai/agents/update_agent_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..09900c45602f8c078cb1251921f12b81bb3b7b48
--- /dev/null
+++ b/ee/spec/services/ai/agents/update_agent_service_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Ai::Agents::UpdateAgentService, feature_category: :mlops do
+  let_it_be(:user) { create(:user) }
+  let_it_be(:agent_version) { create(:ai_agent_version) }
+  let_it_be(:agent) { agent_version.agent }
+  let_it_be(:another_project) { create(:project) }
+  let_it_be(:prompt) { 'prompt' }
+  let_it_be(:name) { 'name' }
+
+  subject(:updated_agent) { described_class.new(agent, name, prompt).execute }
+
+  describe '#execute' do
+    context 'when attributes are valid' do
+      let(:name) { 'new_agent_name' }
+      let(:prompt) { 'new_prompt' }
+      let(:project) { agent.project }
+
+      it 'updates an agent', :aggregate_failures do
+        expect(updated_agent.name).to eq(name)
+        expect(updated_agent.latest_version.prompt).to eq(prompt)
+      end
+    end
+
+    context 'when an invalid name is supplied' do
+      let(:name) { 'invalid name' }
+
+      it 'returns a model with errors', :aggregate_failures do
+        expect(updated_agent.errors.full_messages).to eq(["Name is invalid"])
+      end
+    end
+
+    context 'when the agent version can not be saved' do
+      it 'returns a model with errors', :aggregate_failures do
+        agent.latest_version.model = nil
+
+        expect(updated_agent.errors.full_messages).to eq(["Latest version is invalid"])
+      end
+    end
+  end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 3dcaa309142b8878d89475c66b336611a619b14f..2a23e8696fab7208d086b01a41513b558c678c6f 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1939,6 +1939,9 @@ msgstr ""
 msgid "AIAgents|New agent"
 msgstr ""
 
+msgid "AIAgents|The requested agent was not found."
+msgstr ""
+
 msgid "AIAgent|AI Agent: %{agentId}"
 msgstr ""
 
@@ -1954,12 +1957,18 @@ msgstr ""
 msgid "AIAgent|Create agent"
 msgstr ""
 
+msgid "AIAgent|Edit Ai Agent"
+msgstr ""
+
 msgid "AIAgent|Prompt (optional)"
 msgstr ""
 
 msgid "AIAgent|Try out your agent"
 msgstr ""
 
+msgid "AIAgent|Update agent"
+msgstr ""
+
 msgid "AIAgent|Your agent's system prompt will be applied to the chat input."
 msgstr ""