Task vs Fixlet Scheduling via API

I use PowerShell to schedule Actions on groups in the future. Whether scheduling a fixlet or a task, the initial action works well. However, if I move a computer from one group to another - it only works if the action is a fixlet.

If a fixlet is scheduled on a group, and I move a computer in or out of that group, the computer will either take on or remove the action based on its group membership.

If a task is scheduled, however, the computer will get the action initially, but if I move the computer in or out of the group, the task will stay with the computer.

The question is why? What is the fundamental difference from a fixlet and a task that would cause this?

Can you share the <Relevance> and <Settings> sections of the XML you’re leveraging with the API?

If I’m understanding the scenario you’re describing, you may want to have re-apply behavior that has a time period specified between intervals:

<Reapply>true</Reapply>
<HasReapplyLimit>false</HasReapplyLimit>
<HasReapplyInterval>true</HasReapplyInterval>
<ReapplyInterval>PT15M</ReapplyInterval>

Here is the XML Tamplate I am using:

<?xml version="1.0" encoding="UTF-8"?>
<BES xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="BES.xsd">
    <SourcedFixletAction>
        <SourceFixlet>
            <Sitename />
            <FixletID />
            <Action>Action1</Action>
        </SourceFixlet>
        <Target />
        <Settings>
            <HasStartTime />
            <StartDateTimeLocal />
            <HasEndTime />
            <EndDateTimeLocal />
            <UseUTCTime>false</UseUTCTime>
            <ActiveUserRequirement>NoRequirement</ActiveUserRequirement>
            <ActiveUserType>UsersOfGroups</ActiveUserType>
            <UIGroupConstraints>
                <LocalGroup Name="Administrators"/>
            </UIGroupConstraints>
            <HasWhose>false</HasWhose>
            <PreActionCacheDownload>false</PreActionCacheDownload>
            <Reapply>false</Reapply>
            <HasReapplyLimit>true</HasReapplyLimit>
            <ReapplyLimit>3</ReapplyLimit>
            <HasReapplyInterval>false</HasReapplyInterval>
            <HasRetry>true</HasRetry>
            <RetryCount>1</RetryCount>
            <RetryWait Behavior="WaitForInterval">PT10M</RetryWait>
            <HasTemporalDistribution>false</HasTemporalDistribution>
            <ContinueOnErrors>true</ContinueOnErrors>
            <PostActionBehavior Behavior="Nothing"/>
        </Settings>
        <Title />
    </SourcedFixletAction>
</BES>

And the powershell function:

Function ScheduleActionForComputerGroupFromFixlet {
    param (
        [Parameter(Mandatory=$true,
            HelpMessage="Expecting input of the form: https://<bigfix_server>:52311")]
            [string]$APIBaseUrl,
        [Parameter(Mandatory=$true,
            HelpMessage="Path to directory containing XML templates files")]
            [string]$TemplateDirectory,
        [Parameter(Mandatory=$true,
            HelpMessage="XML template filename")]
            [string]$TemplateFile,
        [Parameter(Mandatory=$true,
            HelpMessage="The desired display name of the new action to be created")]
            [string]$ActionTitle,
        [Parameter(Mandatory=$true,
            HelpMessage="e.g. custom, operator, external, master")]
           [string]$SiteType,
        [Parameter(Mandatory=$true)]$SiteName,
        [Parameter(Mandatory=$true)]$FixletID,
        [Parameter(Mandatory=$true)][string]$TargetGroupName,
        [System.DateTimeOffset]$StartDateTime,
        [System.DateTimeOffset]$EndDateTime,
        [bool]$ActionRestartComputer=$false,
        [Parameter(Mandatory=$true)][Microsoft.PowerShell.Commands.WebRequestSession]$WebSession
    )
    $xmlTemplate = $($TemplateDirectory + $TemplateFile)
    if (!(Test-Path -Path $xmlTemplate)) {
        return @("TEMPLATE_NOT_FOUND",$null)
    }
    # Get XML template and update it with input parameter data
    $actionXML = [xml](Get-Content -Path $xmlTemplate)
    $actionXML.BES.SourcedFixletAction.SourceFixlet.Sitename = $SiteName
    $actionXML.BES.SourcedFixletAction.SourceFixlet.FixletID = [string]$FixletID

    # Look up GroupID of the $TargetGroupName
    $allGroups = GetComputerGroupsInSite -APIBaseUrl $APIBaseUrl -SiteType $SiteType -SiteName $SiteName -WebSession $WebSession
    $TargetGroupID = $allGroups[1] | Where-Object {$_.Name -eq $TargetGroupName} | Select-Object -ExpandProperty ID
    if (!($TargetGroupID)) {
        return @("GROUP_NOT_FOUND",$null)
    }

    # PowerShell treats null-valued elements as String instead of XmlElement, so need to cast
    [System.Xml.XmlElement]$xmlTarget = $actionXML.SelectSingleNode('./BES/SourcedFixletAction/Target')
    $customRelevanceElement = $actionXML.CreateElement("CustomRelevance")
    $relevanceString = $('member of group ' + [string]$TargetGroupID + ' of site whose (name of it = "' + $SiteName + '")')
    $relevanceString = $($relevanceString + ' /* group ' + [string]$TargetGroupID + ' = ' + $TargetGroupName + ' */')
    $customRelevanceText = $actionXML.CreateTextNode($relevanceString)
    [void]($customRelevanceElement.AppendChild($customRelevanceText))
    [void]($xmlTarget.AppendChild($customRelevanceElement))
    if ($StartDateTime) {
        $actionXML.BES.SourcedFixletAction.Settings.HasStartTime = 'true'
#        $actionXML.BES.SourcedFixletAction.Settings.StartDateTimeLocal = $StartDateTime.UtcDateTime.ToString('yyyy-MM-dd HH:mm:ss')
        $actionXML.BES.SourcedFixletAction.Settings.StartDateTimeLocal = $StartDateTime.ToString('yyyy-MM-dd HH:mm:ss')
    } else {
        $actionXML.BES.SourcedFixletAction.Settings.HasStartTime = 'false'
        [System.Xml.XmlElement]$xmlStartDateTimeLocal = $actionXML.SelectSingleNode('./BES/SourcedFixletAction/Settings/StartDateTimeLocal')
        [void]($actionXML.BES.SourcedFixletAction.Settings.RemoveChild($xmlStartDateTimeLocal))
    }
    if ($EndDateTime) {
        $actionXML.BES.SourcedFixletAction.Settings.HasEndTime = 'true'
#        $actionXML.BES.SourcedFixletAction.Settings.EndDateTimeLocal = $EndDateTime.UtcDateTime.ToString('yyyy-MM-dd HH:mm:ss')
        $actionXML.BES.SourcedFixletAction.Settings.EndDateTimeLocal = $EndDateTime.ToString('yyyy-MM-dd HH:mm:ss')
    } else {
        $actionXML.BES.SourcedFixletAction.Settings.HasEndTime = 'false'
        [System.Xml.XmlElement]$xmlEndDateTimeLocal = $actionXML.SelectSingleNode('./BES/SourcedFixletAction/Settings/EndDateTimeLocal')
        [void]($actionXML.BES.SourcedFixletAction.Settings.RemoveChild($xmlEndDateTimeLocal))
    }
    if ($ActionRestartComputer) {
        $actionXML.BES.SourcedFixletAction.Settings.PostActionBehavior.Behavior = 'Restart'
    }
    $actionXML.BES.SourcedFixletAction.Title = $ActionTitle
    $uri = $($APIBaseUrl + "/api/actions")
    $body = $actionXML.OuterXml

    Try {
        $response = Invoke-WebRequest -UseBasicParsing -SkipCertificateCheck -Uri $uri -Method Post -ContentType "application/xml" -Body $body -WebSession $WebSession -ErrorAction Stop | Out-Null
    } Catch {
        return @("REQUEST_FAILED",$null)
    }
    $returnVal = New-Object -TypeName System.Collections.ArrayList
    foreach ($action in ([xml]($response.Content)).BESAPI.Action) {
        [void]($returnVal.Add(
            [pscustomobject]@{
                ID = $action.ID;
                Name = $action.Name
            }
        ))
    }
#    return @("OK",$returnVal)
    return @($null,$returnVal)
}

And how I call it:

ScheduleActionForComputerGroupFromFixlet -APIBaseUrl $APIBaseUrl -TemplateDirectory $TemplateDirectory -TemplateFile $TemplateFile -ActionTitle $ActionTitle -SiteType $SiteType -SiteName $SiteName -FixletID '3550781' -TargetGroupName $SqlROw.name -StartDateTime $StartDateTime -EndDateTime $EndDateTime -WebSession $Session[1]

There are variables obviously that are defined elsewhere in the script, but this is the meat of it. Again, runnign this exact code on the FIXLET works as expected, but on a TASK is where I have the problem. Just wondering why.