#1) in %SYS find the sessions by this Stored Procedure:

#2 Next based on the SessionId I can open the Object
 

%SYS>set sess=##class(%CSP.Session).%OpenId("kTkyVXwgxw")
%SYS>set pid=sess.ProcessId
%SYS>if $l(pid) set tSC=$$DeleteSession^%SYS.cspServer(pid)

The last row was found in  
Class %CSP.UI.Portal.CSPSessions
ClassMethod EndSession

Attention. Not every CSP Session has also a pid ! 

OK

To Stream needs 1 line 2 statements
 

ClassMethod personsidGET(messageRequest As dc.Sample.v3rest.requests.personsidGET) As %Stream.Object
{
 set stream=##class(%Stream.TmpCharacter).%New(),sc=##class(dc.Sample.Person).%OpenId(messageRequest.pathid).%JSONExportToStream(.stream)
 return stream
 }

To String is shorter (just 1 statement) as you don't need to initialize %String)

ClassMethod personsidGET(messageRequest As dc.Sample.v3rest.requests.personsidGET) As %String
 do ##class(dc.Sample.Person).%OpenId(messageRequest.pathid).%JSONExportToString(.string)
 return string
{

not just Sample.Person but also Sample.Address,
or whatever serial class you refer to require %JSON Adaptor.
then

set person=##class(Sample.Person).%OpenId(3)
>set sc=person.%JSONExportToString(.Jperson)
set zjson={}.%FromJSON(Jperson)
ZWRITE
Jperson="{"LIMIT":103,"Name":"O'Rielly,Xavier E.","SSN":"331-77-5308","DOB":"1957-05-26","Home":{"Street":"8757 Elm Place","City":"Miami","State":"FL","Zip":"92027"},"Office":{"Street":"413 First Drive","City":"Miami","State":"NH","Zip":"83830"},"Age":67,"RowVer":0}"
person=<OBJECT REFERENCE>[2@Sample.Person]
sc=1
zjson=<OBJECT REFERENCE>[13@%Library.DynamicObject]

and there is your dynamic object

do ^ADMIN  indicates that you run a classic straight ObjectScript program.
while WRITE just has 1 direction to act  READ is bi-directional.
READ can send some text as prompt and waits for reply.
The only bi-directinal device I know of are network connections as TCP, UDP, TRM,FTP,..
The common feature is : they communicate out of your IRIS instance.

Inside IRIS 
you may do a redirection e.g to some TCP port like |TCP|7000
but then this port is blocked. No other process can touch |TCP|7000.
So you need an external port wrapper to some other port. e.g. |TCP|7100

Then you can handle this bi-directional communication either by sequence
or you have a list of prompts and the expected replies or similar. 

The sequence of operation could then be:

  • have a STARTER that runs in background
    • initiate the external wrapper 
    • run do ^ADMIN
  • start the FOREGROUND 
    • connect to external wrapper
    • send prompts to terminal
    • get replies from external file
    • send it back to port
    • which forwards it to  ^ADMIN hanging in background

 The most tricky point is to handle situations where the communication
if it is not just 1 Prompt :=> 1 Answer  but
multiple Prompts or WRITEs  :=>1 Answer or 1 Prompt :=> multiple Answers.

So I'd suggest instead of an IRIS internal solution rather look for an
external Terminal program to consume and apply your answer script.  
 

From Ensemble.inc:
 

#define TRACE(%arg)             $$$catTRACE("user",%arg)
#define sysTRACE(%arg)          $$$catTRACE("system",%arg)
#define catTRACE(%cat,%arg)     Do:$$$DoTrace ##class(Ens.Util.Trace).WriteTrace(%cat,$$$CurrentClass,$$$CurrentMethod,%arg)
#;
#define DoTrace                 $S($D($$$EnsJobLocal("DoTrace")):$$$EnsJobLocal("DoTrace"),1:##class(Ens.Util.Trace).DoTrace())
#;
#define EnsJobLocal         %Ensemble
#;
. . . . 
Class Ens.Util.Trace [ Abstract, ClassType = "", ProcedureBlock, System = 4 ]
{
ClassMethod DoTrace()
{
	Set tJobConfigName=$$$JobConfigName
	Quit $G($$$ConfigTrace(tJobConfigName),0)||(""'=$G($$$JobTraceDevice))||$$$IsTerminalDevice($IO)
}