---
title: "Create an agent"
slug: "create-an-agent"
abstract: ""
---
# Create an agent

You can create an agent that inherits `BaseAgent` or `RecurringAgent`, and you can choose whether or not the agent should scale. Reasons to create a custom agent include:

- Perform regularly scheduled maintenance within the engine, such as purging expired data from a database that the engine relies on. By default, the Processing Engine includes two agents that perform maintenance tasks.

> [!note]
> It is rare that you will need to create a custom agent. It is more likely that you will create a custom processing worker that will be executed by the default `TaskAgent`.

## Create an agent that inherits RecurringAgent

The following sample agent calls a method that cleans up data in a fake storage provider. The storage provider is represented by the `ICustomProvider` interface. The agent inherits `RecurringAgent`, which means it will run at regular, configurable intervals.

### Create an agent class

To create the agent class:

- Create a class and copy the following sample agent.

> [!note]
> The sample `ICustomProvider` and `CustomProvider` classes are included in the same file for convenience.

```csharp
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Sitecore.Framework.Conditions;
using Sitecore.Processing.Engine.Abstractions;
using Sitecore.Processing.Engine.Agents;

namespace Sitecore.Documentation.Examples
{
    /// <summary>
    ///     Provides basic agent functionality and services.
    /// </summary>
    public class SampleCleanupAgent : RecurringAgent
    {
        private readonly ICustomProvider _customProvider;

        /// <summary>
        ///
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="options"></param>
        /// <param name="customProvider"></param>
        protected SampleCleanupAgent(ILogger<IAgent> logger, IConfiguration options, ICustomProvider customProvider) : base(options, logger)
        {
            Condition.Requires(customProvider, nameof(customProvider)).IsNotNull();

            _customProvider = customProvider;
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        protected override async Task RecurringExecuteAsync(CancellationToken token)
        {
            // Checks if cancellation has been requested in case task is long-running
            // It is your responsibility to check the status of the cancellation token
            while (!token.IsCancellationRequested)
            {
                await _customProvider.CleanData().ConfigureAwait(false);
            }
        }
    }

    /// <summary>
    ///
    /// </summary>
    public interface ICustomProvider {
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        Task GetData();
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        Task CleanData();
    }

    /// <summary>
    ///
    /// </summary>
    public class CustomProvider : ICustomProvider
    {
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public async Task CleanData()
        {
            // Clean up data in custom data provider
            await Task.Delay(1).ConfigureAwait(false);
        }

        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public async Task GetData()
        {
            // Get data from custom data provider
            await Task.Delay(1).ConfigureAwait(false);
        }
    }
}
```

### Register agent and services in configuration

1. Create a file named sc.Processing.Engine.CustomAgents.xml in <engine-root>\\\\App_Data\\\\Config\\\\Global.
2. Register `SampleCleanupAgent` and `ICustomProvider` as shown. This example uses simple configuration to register a single agent.

```xml
<Settings>
        <Sitecore>
            <Processing>
            <Services>
                <ICustomProvider>
                    <Type>Sitecore.Documentation.Examples.CustomProvider, Sitecore.Documentation.Examples</Type>
                    <As>Sitecore.Documentation.Examples.ICustomProvider, Sitecore.Documentation.Examples</As>
                    <LifeTime>Transient</LifeTime>
                </ICustomProvider>
                <SampleCleanupAgent>
                    <Type>Sitecore.Documentation.Examples.SampleCleanupAgent, Sitecore.Documentation.Examples</Type>
                    <As>Sitecore.Processing.Engine.Abstractions.IAgent, Sitecore.Processing.Engine.Abstractions</As>
                    <LifeTime>Transient</LifeTime>
                    <Options>
                        <!-- The period which the agent sleeps before running again. -->
                        <SleepPeriod>0.`00:00`:14.000</SleepPeriod>
                    </Options>
                </SampleCleanupAgent>
            </Services>
            </Processing>
        </Sitecore>
    </Settings>
```

Alternatively, if the agent needs to scale, use `ParallelAgentsConfiguration` to register it:

```xml
<Settings>
        <Sitecore>
            <Processing>
            <Services>
                <ICustomProvider>
                    <Type>Sitecore.Documentation.Examples.CustomProvider, Sitecore.Documentation.Examples</Type>
                    <As>Sitecore.Documentation.Examples.ICustomProvider, Sitecore.Documentation.Examples</As>
                    <LifeTime>Transient</LifeTime>
                </ICustomProvider>
                <SampleCleanupAgent>
                    <Type>Sitecore.Processing.Engine.Agents.ParallelAgentsConfiguration, Sitecore.Processing.Engine</Type>
                    <As>Sitecore.XConnect.DependencyInjection.Abstractions.IXConnectServicesConfiguration, Sitecore.XConnect.DependencyInjection</As>
                    <LifeTime>Transient</LifeTime>
                    <Options>
                        <AgentFixedCount>0</AgentFixedCount>
                        <AgentCoreRatio>0.75</AgentCoreRatio>
                        <AgentConfiguration>
                            <Type>Sitecore.Documentation.Examples.SampleCleanupAgent, Sitecore.Documentation.Examples</Type>
                            <As>Sitecore.Processing.Engine.Abstractions.IAgent, Sitecore.Processing.Engine.Abstractions</As>
                            <LifeTime>Transient</LifeTime>
                            <Options>
                                <SleepPeriod>0.`00:00`:14.000</SleepPeriod>
                            </Options>
                        </AgentConfiguration>
                    </Options>
                </SampleCleanupAgent>
            </Services>
            </Processing>
        </Sitecore>
    </Settings>
```

## Create an agent that inherits BaseAgent

The following sample agent writes a message to the log on startup and waits 1 millisecond. The agent does not inherit `RecurringAgent` and will not run at regular intervals.

> [!important]
> This particular agent runs once on engine startup. However, your agent might sleep until a particular event occurs, then sleep again until the event happens again. The agent does technically 'recur', but not at regularly scheduled intervals.

### Create an agent class

To create an agent class:

- Create a class and copy the following sample agent.

    ```csharp
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Logging;
    using Sitecore.Processing.Engine.Abstractions;
    using Sitecore.Processing.Engine.Agents;

    namespace Sitecore.Documentation.Examples
    {
        /// <summary>
        ///     Provides basic agent functionality and services.
        /// </summary>
        public class SampleLogAgent : BaseAgent
        {
            /// <summary>
            ///
            /// </summary>
            /// <param name="logger"></param>
            /// <param name="options"></param>
            protected SampleLogAgent(ILogger<IAgent> logger, IConfiguration options) : base(logger, options)
            {
            }

            /// <summary>
            ///
            /// </summary>
            /// <param name="token"></param>
            /// <returns></returns>
            public override async Task ExecuteAsync(CancellationToken token)
            {
                    // Write a custom log message
                    //  No cancellation token check in this example as task is unlikely to be long-running
                    base.Log.LogInformation("Your custom agent has started.");
                    await Task.Delay(1).ConfigureAwait(false);
            }
        }
    }
    ```

### Register agent in configuration

1. Create a file named sc.Processing.Engine.CustomAgents.xml in <engine-root>\\\\App_Data\\\\Config\\\\Global.
2. Register `SampleCleanupAgent` as shown. This example uses simple configuration to register a single agent.

    ```xml
    <Settings>
            <Sitecore>
                <Processing>
                <Services>
                    <SampleLogAgent>
                        <Type>Sitecore.Documentation.Examples.SampleLogAgent, Sitecore.Documentation.Examples</Type>
                        <As>Sitecore.Processing.Engine.Abstractions.IAgent, Sitecore.Processing.Engine.Abstractions</As>
                        <LifeTime>Transient</LifeTime>
                    </SampleLogAgent>
                </Services>
                </Processing>
            </Sitecore>
        </Settings>
    ```

## Task cancellation

All If you implement an agent that may result in a long-running task, make sure that you check `token.IsCancellationRequested` property in the `ExecuteAsync` method (for agents inheriting `BaseAgent`) or the `RecurringExecuteAsync` method (agents inheriting `RecurringAgent`).