TcGen Agent

AI-assisted Structured Text generation directly from the TwinCAT engineering shell.

The plugin connects Visual Studio / TwinCAT XAE Shell to Agile Automation's cloud AI service, while a local bridge reads the project and applies approved Structured Text changes through TwinCAT automation.
TwinCAT AI agent

A Visual Studio plugin that lets AI work with real TwinCAT projects.

Project-aware AI

TcGen Agent brings AI assistance into Visual Studio and TwinCAT XAE Shell. It can explain the open project, draft Structured Text, and prepare changes that are applied through the local TwinCAT engineering tools after review.

TwinCAT stays on the engineering workstation. Agile Automation's cloud service handles login, usage limits, model selection, and AI reasoning, while the local bridge reads the project and applies approved updates. TcGen Agent supports TwinCAT 3.1 Build 4024 and 4026+ shell generations.

AI that understands the open TwinCAT project

When you ask for help, TcGen Agent shares the relevant project context with Agile Automation's AI service so the answer is based on your actual TwinCAT solution, not a blank prompt. A local bridge handles project reads and approved writes on the engineering workstation.

Structured Text generation and controlled project updates

TcGen Agent can draft Structured Text and, after approval, update DUTs, functions, interfaces, function blocks, methods, and programs through the standard TwinCAT automation interface.

Write control inside the engineering shell

You choose how project writes are handled: ask every time, approve automatically, or read-only. In ask mode, the generated Structured Text can be reviewed and edited before it is applied.

Read and explain existing projects

The local bridge can read source-controlled TwinCAT project files such as .plcproj, .TcPOU, .TcDUT, .TcGVL, and .xti, then give the AI the code it needs to explain the project accurately.

Generate reviewable Structured Text

Ask TcGen Agent to produce Structured Text for new blocks, methods, interfaces, data types, and example programs while keeping the generated code visible to the developer.

Plan, create, or apply changes

TcGen Agent can recommend a change, create new TwinCAT objects, or apply updates to an existing solution after approval.

Architecture
Docked TcGen Agent tool window inside Visual Studio / TwinCAT XAE Shell
Cloud account login, subscription status, usage limits, and model selection
Local project bridge starts from the plugin and listens only on the workstation
Project reads do not change files; they give the AI the code needed for useful answers
Approved writes can create new TwinCAT solutions or update existing Structured Text
Review dialog shows generated Structured Text before it is written
TcGen Agent in action

Ask for architecture recommendations, document logic, then approve generated Structured Text.

These examples show three concrete TcGen Agent workflows: project-aware architecture review, full documentation generation, and a reviewed write request for new Structured Text.
1

Analyze the open project

TcGen Agent works from the active TwinCAT solution, so recommendations can refer to real function blocks, DUTs, methods, actions, and project structure.

2

Document and explain code

The agent can turn existing Structured Text into readable documentation without losing the engineering detail.

3

Ask before writing

When the agent generates code, the engineer can review the proposed Structured Text before it is written to TwinCAT.

Architecture review

Does it sound familiar to you?

In this anonymized example, TcGen Agent reviewed an existing filling line project and returned prioritized, project-aware recommendations instead of a generic checklist.

You - 09:42
What architectural changes would you suggest?
TC
Assistant - architectural recommendations

Now I have a thorough understanding of the codebase. Here are my architectural recommendations:

Architectural Recommendations for FillingLine Project

1. 🔴 CRITICAL: Massive Duplication of Drive Service Reset Code

Problem: The exact same block of ~30 lines resetting all drive service flags (brake release, homing, manual) is duplicated in 3 places:

  • SR_LineController.Startup_active (init sequence)
  • SR_LineController.ManualMode_exit (on leaving manual mode)
  • SR_LineController.ManualStop_active (stop manual)

This is a maintenance nightmare — adding a new axis means updating all 3 locations.

Recommendation: Extract into a single function:

Recommended extractionST
FUNCTION F_ResetAllDriveServiceFlags
VAR_IN_OUT
    iq_stRuntime : ST_RuntimeInterface;
END_VAR

// Single source of truth for all drive resets

Then call F_ResetAllDriveServiceFlags(stRuntime) from all 3 places.

2. 🟡 HIGH: SR_LineController Declaration Section is a God Object

Problem: SR_LineController's declaration section contains ~80+ local variables spanning safety, alarming, format change, machine mode, transport mode, controller, machine signals, motion, light grid, IPC, and more. This is a flat, unstructured declaration that mixes concerns.

Recommendation: Group related variables into local structs:

Grouped declarationsST
VAR
    stSafety   : ST_LineController_Safety;
    stAlarming : ST_LineController_Alarming;
    stFormat   : ST_LineController_FormatChange;
    stMode     : ST_LineController_MachineMode;
    ...
END_VAR

This improves readability and makes it easier to refactor sub-functionality into separate function blocks later.

3. 🟡 HIGH: NWL (Ladder/Function Block Diagram) Actions Should Be Converted to ST

Problem: Many SR_LineController actions are implemented in NWL (Network/Ladder) format — InputProcessing_active, ControllerLogic_active, OperationMode_active, ServiceMode_active, OutputProcessing_active, etc. This is:

  • Harder to version-control (XML serialization of graphical elements)
  • Harder to review in code diffs
  • Slower to edit programmatically

Recommendation: Convert all NWL actions to Structured Text (ST). For example, ControllerLogic_active (3 AND gates with latches) is trivial in ST:

Controller logic in STST
xModeReady    := xActOperation OR xActService;
xActOperation := xInputOperation AND xModeReady;
xActService   := xInputService AND xModeReady;

4. 🟡 MEDIUM: Format Change Logic is Fragile

Problem: The format change detection in GlobalServices_active compares 8+ hardware cam data values against stored "temp" variables. This is:

  • Hardcoded — adding a new cam axis means adding another OR condition and another temp variable
  • Brittle — the comparison uses <> which fails on REAL precision issues
  • Incomplete — only checks filling needle and pre-seal placement, but not rotor centring, outlet, or sealing axes

Recommendation: Create a dedicated FB_FormatChange function block:

Format change function blockST
FUNCTION_BLOCK FB_FormatChange
VAR_INPUT
    i_astCamData : ARRAY [*] OF ST_CamSnapshot;
END_VAR
VAR_OUTPUT
    q_xFormatChanged : BOOL;
END_VAR

With a method to register cam data sources and compare with configurable tolerance.

5. 🟡 MEDIUM: Missing Sealing Equipment Module

Problem: The project has EM_01 (Global), EM_02 (Transport), EM_03 (Filling), EM_04 (PreSealing) — but no EM for final sealing/crimping. The SR_LineController declaration has temp variables for rSealCrimpingStartPositionTemp and rSealCrimpingCrimpPositionTemp that are declared but never used in the format change logic (commented out or missing). This suggests sealing was planned but not yet implemented.

Recommendation: Either implement EM_FinalSealing or remove the unused variables to avoid confusion.

6. 🟡 MEDIUM: Persistent Data Strategy

Problem: Only stRuntime and stController are PERSISTENT. The AxisRestoreStore GVL (RETAIN PERSISTENT) stores axis restore positions separately. This split means:

  • If the PLC is cold-started, axis restore positions are lost (RETAIN only)
  • The relationship between stRuntime and axis positions is unclear

Recommendation: Move axis restore positions into stRuntime as a nested struct, or at minimum document the persistence strategy clearly.

7. 🟢 LOW: Machine Configuration is Hardcoded

Problem: In OutputProcessing_active, EXUNIT.FC_LineConfiguration is called with hardcoded literals:

Hardcoded configurationST
i_uiMachineType := 50;
i_xVials := TRUE;
i_xInletTurntable := TRUE;
i_uiObjectsPerHolderMax := 6;
i_uiObjectsPerHolderMin := 3;
...

Recommendation: Move these to a configuration GVL or the ST_LineConfig struct so they can be changed without modifying the program code.

8. 🟢 LOW: Error Quit Logic is Scattered

Problem: Error quit processing happens in:

  • InputProcessing_active (TP + R_TRIG for the button)
  • GlobalServices_active (output forwarding logic)
  • ModuleDispatch_active (forwarded to each EM)

The TON_VendorErrorQuit and TP_VendorErrorQuit in SR_LineController suggest a vendor-specific workaround that's mixed with the main logic.

Recommendation: Encapsulate all error quit handling into a single FB_ErrorQuit function block with configurable pulse timing and vendor-specific extensions.

9. 🟢 LOW: IPC Correction Array Update is Inefficient

Problem: In GlobalServices_active:

Every-cycle IPC copyST
FOR i:= 1 TO EXUNIT.LineConfig.g_c_uiStandardObjectCount DO
    stController.arProcessCorrection[i] := stRuntime.stTransport.stRotor.stVal.astNetWeightIpc[i].rCorrection;
END_FOR

This copies the entire array every cycle, even when nothing changed.

Recommendation: Use MEMCPY (from Tc2_Utilities) or only update on change detection.

10. 🟢 LOW: No Unit Testing / Simulation Harness

Problem: The project has no test infrastructure. With 226 files and complex SFC state machines, manual testing is the only option.

Recommendation: Consider adding:

  • A SR_TestSimulation program that can inject test values into stHardware inputs
  • A test sequence SFC that exercises each machine mode
  • TcUnit or a custom test framework

Summary Priority Matrix

PriorityChangeEffortRisk
🔴 CriticalExtract drive reset duplicationLowLow
🟡 HighConvert NWL → ST actionsMediumMedium
🟡 HighStruct-ify SR_LineController declarationsLowLow
🟡 MediumFB_FormatChange for cam detectionMediumLow
🟡 MediumImplement or remove sealing EMHighMedium
🟡 MediumClean up persistence strategyLowLow
🟢 LowExternalize machine configLowLow
🟢 LowEncapsulate error quitLowLow
🟢 LowOptimize IPC copyLowLow
🟢 LowAdd test harnessHighLow

Would you like me to implement any of these changes? I'd recommend starting with #1 (drive reset duplication) and #4 (format change FB) as they provide immediate maintainability benefits with low risk.

TcGen Agent conversation
You - 10:59
Can you write Markdown documentation for the traffic light function block?
TC
Assistant - documentation
Download MDDownload PDF

Traffic light simulation function block FB_Ampel

Overview

FB_Ampel is a TwinCAT 3 function block that simulates a standard traffic light sequence. It cycles through Red, RedYellow, Green, Yellow, and back to Red with fully configurable phase durations. It is designed for HMI lamp widgets, physical signal towers, or status indicators on automated machinery.

Dependencies

DependencyTypePurpose
E_AmpelStateEnum DUTDefines the traffic light states
TONTimerPhase timing
E_AmpelState enumST
TYPE E_AmpelState :
(
    eRed       := 0,
    eRedYellow := 1,
    eGreen     := 2,
    eYellow    := 3
);
END_TYPE

Interface

Inputs
  • xEnable: starts the cycle; FALSE resets to red.
  • tRedDuration: red phase, default T#5s.
  • tRedYellowDuration: transition phase, default T#1s.
  • tGreenDuration: green phase, default T#4s.
  • tYellowDuration: yellow phase, default T#1s.
Outputs
  • eState: current traffic light state.
  • xRed, xYellow, xGreen: lamp outputs.
  • xCycleActive: TRUE while the cycle is actively running.

State machine and default timing

Red
5s default
RedYellow
1s default
Green
4s default
Yellow
1s default

The default total cycle time is 11 seconds.

Behavior details

When enabled
Starts at red, runs each configured timer, advances through the phases, and loops back to red after yellow.
When disabled
Immediately resets to red, stops the timer, turns yellow and green off, and marks the cycle inactive.
Lamp logic
At the start of every cycle call, all lamps are cleared. The active state then sets the matching lamp outputs.

Usage examples

Basic instantiationST
PROGRAM MAIN
VAR
    fbTrafficLight : FB_Ampel;
END_VAR

fbTrafficLight(xEnable := TRUE);
Custom timingST
fbTrafficLight(
    xEnable            := TRUE,
    tRedDuration       := T#10s,
    tRedYellowDuration := T#2s,
    tGreenDuration     := T#8s,
    tYellowDuration    := T#2s
);
Reading lamp statesST
HmiLampRed     := fbTrafficLight.xRed;
HmiLampYellow  := fbTrafficLight.xYellow;
HmiLampGreen   := fbTrafficLight.xGreen;
HmiLightActive := fbTrafficLight.xCycleActive;
Conditional controlST
fbTrafficLight(
    xEnable := gxMachineAuto AND NOT gxAlarmActive
);

Internal variables

VariableTypeDescription
fbTimerTONTimer used to measure each phase duration
eNextStateE_AmpelStateReserved for future extensions; currently written but not read

Notes

  • The block uses a single TON timer that is reset on each state transition.
  • All timing parameters have defaults, so the block runs without configuration.
  • The block is self-contained and needs no global variables to operate.
Send a request to the TcGen agent
Normal reasoning
Write request
You - 15:18
Create an object-oriented base block named FB_Stepchain that can be inherited by blocks that use stepchains.
Approval required - 15:19

A TwinCAT write request is waiting for approval in the TwinCAT shell.

Tool: tcgen_apply_existing_solution
Solution: C:\Projects\TwinCAT\TestTcGenAgent\TestTcGenAgent.sln
PLC project: TestTcGenAgent
Write control: ask

Approve or deny this write from the local dashboard or from the TwinCAT XAE Shell approval window.

Complete generated Structured TextST
TYPE E_StepState :
(
    eStepIdle     := 0,
    eStepRunning  := 1,
    eStepComplete := 2,
    eStepError    := 3
);
END_TYPE

FUNCTION_BLOCK FB_Stepchain
VAR_INPUT
    xEnable : BOOL;    (* Enable the step chain execution *)
    xReset  : BOOL;    (* Reset the step chain to idle *)
END_VAR
VAR_OUTPUT
    nStep : UINT;              (* Current active step number *)
    eState : E_StepState;      (* Current state of the step chain *)
    xStepActive : BOOL;        (* TRUE when a step is executing *)
    xChainComplete : BOOL;     (* TRUE when all steps have completed *)
END_VAR
VAR
    nMaxSteps : UINT := 10;
    rTrigEnable : R_TRIG;
    rTrigReset : R_TRIG;
    rTrigAdvance : R_TRIG;
    xAdvanceRequested : BOOL;
END_VAR

rTrigEnable(CLK := xEnable);
rTrigReset(CLK := xReset);

IF rTrigReset.Q OR (xReset AND NOT xEnable) THEN
    nStep := 0;
    eState := eStepIdle;
    xChainComplete := FALSE;
    xAdvanceRequested := FALSE;
    RETURN;
END_IF

IF rTrigEnable.Q THEN
    nStep := 1;
    eState := eStepRunning;
    xChainComplete := FALSE;
END_IF

IF eState = eStepRunning THEN
    rTrigAdvance(CLK := xAdvanceRequested);

    IF rTrigAdvance.Q THEN
        IF nStep >= nMaxSteps THEN
            nStep := 0;
            eState := eStepComplete;
            xChainComplete := TRUE;
            xAdvanceRequested := FALSE;
        ELSE
            nStep := nStep + 1;
            xAdvanceRequested := FALSE;
        END_IF
    END_IF;
END_IF

xStepActive := (eState = eStepRunning) AND (nStep > 0);


METHOD m_xAdvance : BOOL
VAR_INPUT
    xExecute : BOOL;
END_VAR

IF xExecute THEN
    xAdvanceRequested := TRUE;
    m_xAdvance := TRUE;
ELSE
    m_xAdvance := FALSE;
END_IF


METHOD m_xIsActiveStep : BOOL
VAR_INPUT
    nStepNumber : UINT;
END_VAR

m_xIsActiveStep := (eState = eStepRunning) AND (nStep = nStepNumber);
Approve writeDenyCopy ST
TcGen plans

Public monthly plans for individual engineers, teams, and OEMs.

Start with a single engineer seat, expand to a small machine-builder team, or use the professional and enterprise tiers when TcGen Agent becomes part of regular TwinCAT delivery.
Single seat

Engineer

€149/month

Solo engineer, low-friction trial

Low usage quota

A practical entry point for one engineer evaluating project-aware AI in TwinCAT.

Small teams

Team

€690/month

Small machine builder, up to 3 users

Medium usage quota

For small teams that want shared access without enterprise procurement overhead.

TwinCAT teams

Professional

€1,500/month

Serious TwinCAT team, up to 10 users

High usage quota

For engineering groups using TcGen Agent across active machine software work.

OEM rollout

Enterprise

Custom

Larger OEMs, self-hosted, privacy review, procurement

Custom usage quota

For larger organizations that need deployment, privacy, and procurement alignment.

Interested in AI-assisted TwinCAT project analysis or code generation?

Tell us what you are building, where the current blocker is, and what the target architecture should support.

Contact