Events raised by a legacy agent
This feature is still being finalized by Development.
See Relays, Agents and agent pools and Event log.
A job — or any process — running on a legacy LSAM machine can raise an OpCon Continuum event without an inbound network path to the platform. It writes a file of OpCon event syntax into the agent's MSGIN directory; the agent picks the file up, sends each line to Continuum over the connection it already holds open through its relay, and Continuum applies it.
Each line carries its own credential pair, which Continuum verifies and then checks against that service account's roles — so the machine needs a credential for this channel, but nothing on it holds an interactive Continuum sign-in.
The agent side of this already ships in every installed Windows and UNIX/Linux LSAM. Nothing on the machine has to change, and existing event files carry over unmodified.
This applies only to legacy agents reached through a relay. Universal agents have no MSGIN directory, and the setting described below is not offered for them.
Before any event can be applied: Default event environment
Every event raised this way is applied to one environment, named on the agent's own registration.
| Where | Agents → Legacy Agents & Groups, on the register or edit dialog for a legacy agent |
| Field | Default event environment — an optional list of the tenant's environments |
| Unset | Every event that machine raises is refused. There is no fallback to "the only environment" or "the first environment" |
| Clearing it | Clears the setting back to unset, which stops every event that machine raises |
An unset Default event environment refuses events uniformly — not just the ones that address a schedule or a job. The machine has already deleted the event file by the time Continuum sees the line, so a refused event cannot be recovered by retrying: the process has to raise it again.
One machine resolves to one environment, and there is no per-event override. A machine that is shared across environments still sends everything to its configured default. The environment cannot be carried in the event text instead, because an event line names a schedule, not an environment, and the same schedule name legitimately exists in more than one environment.
The environment is read from the agent's registration on the platform side, so it cannot be overridden by anything the machine sends.
What a line has to look like
Continuum treats an inbound line as an event when it starts with $ or #, followed by a name, a
colon, a second name, and then a comma — for example:
$JOB:ADD,CURRENT,DAILY,MYJOB,Mon-Fri,opconuser,mytoken
$PROPERTY:ADD,DISK_PCT_PROD01,84,opconuser,mytoken
Anything else on the connection is handled as it always was, so this cannot disturb job status or machine up/down reporting.
The trailing credential pair is mandatory, and it is now verified
Every line must end with two extra comma-separated values: a login ID and a token. This matches the legacy format, so files written for a legacy server work unchanged — and it is why a hand-authored line that omits them is refused.
The pair is checked. Earlier builds parsed it, masked it and recorded it, and then did not verify it — any machine that could write to its own MSGIN directory could raise any admitted event with no valid credential at all. Continuum now presents the pair to the Continuous identity system and rejects the line if it does not check out.
What a working credential is:
| The token | A service-account secret issued by the Continuous identity system for this tenant. A Classic external token is not one, so it has to be replaced |
| The login ID | Must be the name of the service account that secret belongs to, compared ignoring case. The account name is what is verified against, so the login IDs already in your event files can stay as they are — you create service accounts named to match |
| What is recorded | The verified account name, against the event. The token is never persisted and appears in no record you can read |
- The field count is strict and includes the pair. A line with the wrong number of values is refused rather than partly applied — including a line that ends in a stray comma, which the refusal names specifically, because a trailing separator written by the emitting script is the usual cause.
The MSGIN file format, the emitting scripts and the login ID all stay as they are. What changes is the token value in the emitter's configuration: create a service account whose name matches the login ID the file already carries, and put its secret where the old token was. Every Classic login ID carries over verbatim.
Grant that account only the roles it needs. The shipped Classic examples used an administrator login, and copying one is how a full-admin token ends up sitting in a shell script on every machine. A new credential has to be chosen anyway, so this is the moment to narrow it.
Create the account in the Continuous identity system. The Roles list carries an Event Identities action that looks like the place for it, but managing identities from Continuum is switched off and that section will tell you so.
A line whose credential verifies is then checked against that service account's roles, the way a
person's request would be. The account needs the permission the event requires, in the workspace of
the object the event names and in the machine's Default event environment — for example, a
$JOB:KILL line needs permission to delete job instances there. A line carrying
property tokens also needs permission to view every global
property it reads. A line the account may not perform is refused with EVENT_NOT_PERMITTED
before it becomes an event, so it does not appear in the event log. The
events refused for everyone stay refused whatever
the account holds.
So grant each emitter's service account only what its event files need.
- There is no unverified mode. Every line is verified. A tenant the platform has no identity configuration for cannot have any line verified, so every line from that tenant is refused and lost — none is applied, and nothing reaches the event log.
- The literal pair
SYSTEM/MESSAGEis admitted without verification, for compatibility with a shipped legacy emitter. Lines that use it carry no account, so they are not checked against any roles either.
The SYSTEM/MESSAGE compatibility pair
One shipped Windows legacy emitter writes the literal pair SYSTEM,MESSAGE with no customer
configuration at all, and MESSAGE is not a service-account secret. So that exact pair — both
halves, matched ignoring case — is admitted without being verified, or agent notification
dispatch from that emitter would stop working on upgrade.
It is deliberately narrow:
- Only these eight event types are admitted with it:
$CONSOLE:DISPLAY,$NOTIFY:EMAIL,$NOTIFY:LOG,$NOTIFY:NETSEND,$NOTIFY:SNMP,$NOTIFY:SPOAL,$NOTIFY:TASKSand$NOTIFY:TEXTMSG. Any other event type presented with this pair is rejected. $NOTIFY:COMMANDand$NOTIFY:SPOCOare excluded specifically, because both run something.- The match is on the pair, so a real service account that happens to be named
SYSTEMneither gains this treatment nor is shadowed by it. The two are kept apart in the record: an event admitted this way is recorded as having used the compatibility pair and carries no verified identity.
There is no setting that turns this off, and it applies to every tenant. $NOTIFY:EMAIL is in the
eight and takes a caller-supplied recipient, so anything that can write to a machine's MSGIN
directory can send mail to any address, from your tenant, without presenting a credential of its
own. Until $NOTIFY:EMAIL was implemented such a line was recorded and then failed; now it is
delivered.
$NOTIFY:TEXTMSG and $NOTIFY:TASKS also take a caller-supplied recipient, but both are now
refused outright, so neither sends anything.
Treat write access to MSGIN as sensitive on any machine you have not migrated, and restrict the directory accordingly.
The format is positional and comma-separated with no escape character, so an entity name containing a comma shifts every value after it. The field-count rule catches the cases where the total no longer adds up, but a comma inside an earlier value can still produce a line that counts correctly and means something else. Avoid commas in any name an event file refers to.
Which events are applied
Every event family in the catalog is admitted, which matches how the channel is used today: any job on the machine can write to MSGIN, so the platform does not try to guess which families a given site needs. Two narrowings and one gap are worth knowing:
| Rule | Effect |
|---|---|
$MACHINE:STATUS and $MACHINE:MAXJOBS may name only the originating machine | A line naming the machine itself is accepted (and then fails — see below); a line naming another machine is refused |
$MACHINE:* wildcards (*, ?) are refused | A single line cannot address the whole estate |
$MACHINE:* is admitted and then fails | Continuum does not apply $MACHINE:STATUS or $MACHINE:MAXJOBS, so either is accepted at the edge and recorded as FAILED. Nothing is taken out of service |
Eight $NOTIFY:* types are admitted and then refused | $NOTIFY:COMMAND, $NOTIFY:LOG, $NOTIFY:NETSEND, $NOTIFY:SNMP, $NOTIFY:SPOAL, $NOTIFY:SPOCO, $NOTIFY:TASKS and $NOTIFY:TEXTMSG each depended on the OpCon server's own host, or are out of scope, and will not arrive later. The line is recorded FAILED with a message saying to remove or replace it — see why an event type failed |
$NOTIFY:EMAIL from a machine now sends mail. It is the one $NOTIFY type the platform carries
out, and a line that names it is applied like any other: the addresses, subject and body come off the
line, and the message goes out through the same Email channel a notification group uses. A non-empty
attachments field fails the line — there is no filesystem here to read attachment paths from. See
Sending mail with $NOTIFY:EMAIL.
$MACHINE:* failing is deliberate rather than a defect. A green row for one of them would say a
machine had been taken out of service when it had not — the same rule the
event log applies to every event type the platform cannot act on.
$PROPERTY:ADD, $PROPERTY:SET and $PROPERTY:DELETE reach global, OI. and instance-scoped
properties. A machine-scoped (MI.) name is still refused with a message naming the scope, so a
script reporting a per-machine measurement under a machine-scoped name does not work. What does work
now is writing a property onto a run — SI. for a workflow instance, JI. for a job instance.
From a machine, name the workflow and its schedule date in full: SI.DISK_PCT.20260930.NIGHTLY,
or JI.DISK_PCT.20260930.NIGHTLY.EXTRACT. The shorthand that leaves those parts blank defaults them
from the job or workflow that raised the event, and a line written into MSGIN was not raised by
either, so a blank part is refused with Cannot default schedule name: event has no triggering
instance. See
Writing a property onto a running instance.
Property tokens in an event line
A line may carry [[…]] property tokens, and they are resolved as the event is carried out — so
a script can write $SCHEDULE:BUILD,[[OI.REGION]]_DAILY,[[$DATE]],… instead of computing the
schedule name and the date in shell. Earlier builds passed the tokens through as literal text, which
was refused or applied as the characters themselves.
What a line can reach is global properties and the clock ([[$DATE]], [[$TIME]], [[$NOW]]).
A job-, schedule- or machine-scoped token has nothing to resolve against here and fails the
event, as does a name no global property has — the message names the token as the file wrote it.
[[…]] resolution is strict for exactly the reason the event
log is worth reading: a mistyped name that rendered as its own text would look like a
valid value and be applied.
The event type itself must be literal — a token in the first field is refused.
For the full rules, including what happens to an encrypted property and to a value that would carry a comma into the next field, see An event raised from outside a job.
How an agent-raised event is attributed
In the event log, an event raised this way shows:
- Source
AGENT, and anAGENTactor naming the machine that raised it. The machine stays the actor even now that the credential is verified, because that is the field operators filter on. - The service account the credential belongs to — the name the identity system returned, not the name the line claimed. The two agree apart from case, and the record keeps whichever the account actually has.
- The event line as received, with the credential pair stripped and the token masked.
The identity field tells you which of two things happened:
| What the record shows | What it means |
|---|---|
| A verified service account name | The credential was exchanged and checked out, and the account was permitted the event |
| The compatibility pair | The line used SYSTEM/MESSAGE and carries no identity at all |
That is more than the legacy behaviour offered: the file name, line number, emitting process and machine-side timestamp are not on the wire and so are not recorded. The machine name is, and it is the attribution to trace from.
Where a rejected event goes
This matters more than it usually would, because the machine deletes the event file before Continuum has acknowledged anything. There is no error file written back to the machine — there is no channel for one — so the platform's own record is the only trace.
Rejections split into two groups, and only one of them is visible to you:
| Rejected | Where you see it |
|---|---|
At the platform edge — unknown event type, wrong field count, surplus values, an unset Default event environment, a $MACHINE line naming another machine or using a wildcard, a credential that fails verification, a service account without the permission the event needs, a tenant with no identity configuration, a line over 4,096 bytes (which takes its whole batch with it — see Delivery), or an event type the compatibility pair does not cover | Not in the event log. The line never became an event. It is recorded in the platform's operational logs with the machine name, the event type and the reason |
| After the event was accepted — no handler for the type, a refused scope, a downstream failure | In the event log, as a FAILED event with the AGENT source, the machine name, and the error on its detail view |
If a machine's event file is not producing anything and nothing appears in the event log for it, that is consistent with the line being refused at the edge — most often an unset Default event environment or a field count that does not match. Confirm the setting first, then contact support with the machine name and the event type.
Delivery: at most once, and lossy
The channel is not a queue, and this is the legacy behaviour rather than a Continuum choice — the installed agents delete the file before the platform acknowledges anything.
- An event can be lost. A send failure loses the line, and on UNIX/Linux it loses the rest of the file with it, so partial application of a multi-line file is a reachable outcome.
- The relay forwards lines in batches of up to 100, which can come from any of the machines behind it. A batch the relay cannot deliver is dropped whole, and so is a batch the platform refuses whole — which is what happens when any one line in it is over 4,096 bytes. One oversized line can therefore lose up to 99 other events, from other machines as well as its own. Keep every line under 4,096 bytes.
- A line sent twice is applied twice. The relay gives each line its own identity when the line arrives from the agent, so the relay's own retries of a batch are recognised and applied once — but if the agent sends the same line again, it arrives as a new event. Two files with identical contents are likewise two separate events, which is correct — a script reporting the same measurement on a schedule is meant to record each one.
- Ordering must not be relied on, either across files or between lines of one file. If one event has to be applied before another, put them in separate files and wait for the first to appear.
For anything where the outcome matters, treat an event file as a request that usually arrives, and
confirm the result rather than assuming it. The event log, filtered to source AGENT, is where to
confirm.
Platform differences on the machine side
These come from the installed agents and cannot be corrected by the platform, so they are worth knowing when an event file works on one machine and not another.
| UNIX/Linux | Windows | |
|---|---|---|
A line with no leading $ | The agent adds one, so the line still works | Sent as-is, and refused as an unknown event type |
| Very small files | A file of 16 bytes or fewer is ignored and never deleted, so it accumulates in the directory | Handled normally |
| A file still being written | Waits for the file to stop changing | Can read a partly-written file, producing a truncated line that is then refused |
| Non-ASCII text | Passed through byte for byte | Depends on the machine's own code page, and a UTF-8 byte-order mark corrupts the first line |
| Pickup delay | Up to the agent's polling interval — 5 seconds by default | Under a second |
$Both make a file behave the same way on either platform. On Windows, save without a byte-order mark.
Secrets in an agent-raised event
$JOB:ADD, $JOB:ADDHLD, $SCHEDULE:BUILD and $SCHEDULE:BUILDHLD carry a properties field as
Name=Value;Name2=Value2, and event files are written by hand — so a password can end up in one.
When one of these is raised by an agent and its properties field holds a value, that field and the values after it are replaced with a placeholder before the event is stored. The event is still applied with what the script sent; only the stored record is redacted. Two consequences:
- The stored record shows a placeholder rather than the properties you sent, and the verbatim line is not kept for that event. The parsed fields are all still there.
- Retry is refused for such an event, and the message says so: the original value cannot be recovered, so it has to be raised again from the machine that produced it.
An event that authors no properties value is unaffected and keeps its full record.
A $JOB:ADD from an agent never names an instance after a property value. A $JOB:ADD or
$JOB:ADDHLD for a multi-instance
job that carries properties and
finds no Default instance adds an ad-hoc instance, and everywhere else that instance is named
from the first property's value. Raised by an agent it is named AdHoc instead — numbered
AdHoc$0001, AdHoc$0002… if that name is already in use. A job's name is shown in every listing
and log entry of the job and is returned in the event's own state changes and messages, none of
which the redaction above covers, so a value promoted into it would be readable in all of them. The
property values themselves are still set on the instance, exactly as the line sent them.
Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| Nothing happens, and no event appears in the log | No Default event environment on the agent, or the line's field count is wrong | Set the environment on the agent's registration. Check the line ends with the login ID and token values and has no trailing comma |
| Events from a machine stopped working after an upgrade, and nothing appears in the log | The credential is now verified and the line's token is not a service-account secret — or the login ID doesn't match the account the secret belongs to | Create a service account named for the login ID already in the file and replace the token with its secret. See the credential pair |
$JOB:* or $SCHEDULE:* lines from a machine are refused while its $NOTIFY:* lines are applied | The emitter is using the SYSTEM/MESSAGE compatibility pair, which covers only eight event types | Give that emitter a real service-account credential |
| A line with a correct credential is refused, and nothing appears in the log | The credential verified, but the service account's roles don't grant the permission that event needs in the workspace it names and the machine's Default event environment | Grant the account a role with that permission, scoped to that workspace and environment |
| An event is refused shortly after a role change in the identity system | The service account's role was withdrawn, so the credential no longer resolves or no longer carries the permission | Restore the role, or grant the account one that exists and is active |
| Several machines' events went missing at the same moment, and none appears in the log | One line in the relay's batch was over 4,096 bytes, so the whole batch was refused | Find and shorten the long line, then raise the lost events again |
| Every line from the tenant is refused, whatever the credential | The platform has no identity configuration for the tenant, so no line can be verified | Contact support |
The event appears as FAILED with not yet implemented | A $MACHINE:STATUS or $MACHINE:MAXJOBS line | These types are not applied. Use a workflow event or a notification group instead |
The event appears as FAILED saying the type is not supported on this platform | One of the eight refused $NOTIFY types | It will not arrive later. For mail, use $NOTIFY:EMAIL, which does work |
A $NOTIFY:EMAIL line fails naming attachments | Either the field really holds a path, or a comma in the message text shifted the text into it | Clear the field. The line format has no escape for a comma, so keep commas out of the message |
The event appears as FAILED naming a property scope | A machine-scoped (MI.) property name | Global, OI. and instance-scoped (SI./JI./SSI./SJI.) names work; machine-scoped does not |
The event appears as FAILED naming a [[…]] token | The line carries a property token that does not resolve, or one scoped to a job, schedule or machine | Check the global property's name. A line raised this way can reach globals and the clock only — see Property tokens in an event line |
| The event applied to the wrong environment | The machine's Default event environment is not the one you expected | It is per machine, not per event. Change the setting, or raise the event from a machine registered to the right environment |
A $MACHINE:STATUS line for another machine is refused | Only the originating machine may be addressed | Raise it from that machine |
| Files pile up in the directory on a UNIX/Linux machine | Each is 16 bytes or fewer, so the agent ignores them | Pad the line, or combine the content into a larger file |
| The first line of a file is refused on Windows | A byte-order mark, or a line with no leading $ | Save as ASCII without a byte-order mark, and start every line with $ |
Contact support when
- A well-formed line with the environment set produces neither an applied event nor a
FAILEDrow in the event log. - An event applies but its recorded changes do not match what happened.
Include the machine name, the event type, the approximate time, and — if there is one — the event id and correlation id from the event log.